home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / src / gus.asm < prev    next >
Encoding:
Assembly Source File  |  1997-01-16  |  80.4 KB  |  4,272 lines

  1. ;*    GUS.ASM
  2. ;*
  3. ;* Gravis Ultrasound Sound Device
  4. ;*
  5. ;* $Id: gus.asm,v 1.3 1997/01/16 18:41:59 pekangas Exp $
  6. ;*
  7. ;* Copyright 1996,1997 Housemarque Inc.
  8. ;*
  9. ;* This file is part of the MIDAS Sound System, and may only be
  10. ;* used, modified and distributed under the terms of the MIDAS
  11. ;* Sound System license, LICENSE.TXT. By continuing to use,
  12. ;* modify or distribute this file you indicate that you have
  13. ;* read the license and understand and accept it fully.
  14. ;*
  15.  
  16. comment #
  17.  
  18. Preliminary InterWave support added on 08-Mar-1996
  19. by Jarno Petteri Heikkinen (japehe@cc.jyu.fi)
  20.  
  21. historical notes:
  22.  
  23. 13/04/96      "upgraded" gus code from pre-release 4
  24.  
  25. 10/03/96      made somewhat "midas compliant" by defining two different
  26.           cards (gusCardTypes)
  27.           support for InterWave's >4MB memory does not exist
  28.           (cant test it anyway, I have only 2MB)
  29.  
  30. 08/03/96      I dont have a clue about how MIDAS Surround thing works
  31.           so it prolly doesnt :)
  32.  
  33. #
  34.  
  35. IDEAL
  36. P386
  37. JUMPS
  38.  
  39. INCLUDE "lang.inc"
  40. INCLUDE "errors.inc"
  41. INCLUDE "sdevice.inc"
  42. INCLUDE "mmem.inc"
  43. INCLUDE "mglobals.inc"
  44. INCLUDE "mutils.inc"
  45.  
  46. ; This switch determines whether GUS SoundDevice should use full volume
  47. ; ramps when setting instruments (no clicks, but slower) or just faster
  48. ; ramping.  Value 1 sets fast ramps.
  49.  
  50. FASTGUS = 0
  51.  
  52. ;/***************************************************************************\
  53. ;*     enum gusFunctIDs
  54. ;*     ----------------
  55. ;* Description:  ID numbers for GUS Sound Device functions
  56. ;\***************************************************************************/
  57.  
  58. enum    gusFunctIDs \
  59. ID_gusDetect = ID_gus, \
  60. ID_gusInit, \
  61. ID_gusClose, \
  62. ID_gusGetMixRate, \
  63. ID_gusGetMode, \
  64. ID_gusOpenChans, \
  65. ID_gusCloseChans, \
  66. ID_gusClearChans, \
  67. ID_gusMute, \
  68. ID_gusPause, \
  69. ID_gusSetMasterVolume, \
  70. ID_gusGetMasterVolume, \
  71. ID_gusSetAmplification, \
  72. ID_gusGetAmplification, \
  73. ID_gusPlaySound, \
  74. ID_gusReleaseSound, \
  75. ID_gusStopSound, \
  76. ID_gusSetRate, \
  77. ID_gusGetRate, \
  78. ID_gusSetVolume, \
  79. ID_gusGetVolume, \
  80. ID_gusSetSample, \
  81. ID_gusGetSample, \
  82. ID_gusSetPosition, \
  83. ID_gusGetPosition, \
  84. ID_gusGetDirection, \
  85. ID_gusSetPanning, \
  86. ID_gusGetPanning, \
  87. ID_gusMuteChannel, \
  88. ID_gusAddSample, \
  89. ID_gusRemoveSample, \
  90. ID_gusSetUpdRate, \
  91. ID_gusStartPlay, \
  92. ID_gusPlay, \
  93. ID_gusInitHeap, \
  94. ID_gusFreeHeap, \
  95. ID_gusMalloc, \
  96. ID_gusFree, \
  97. ID_gusAllocBlock, \
  98. ID_gusCoreFree
  99.  
  100.  
  101. ;/***************************************************************************\
  102. ;*    ENUM gusCardTypes
  103. ;*    ----------------
  104. ;* Description: Sound Card type number for GUS Sound Device
  105. ;\***************************************************************************/
  106.  
  107. enum    gusCardTypes \
  108.     gusAutoType = 0, \        ; autodetect card type
  109.     gusGF1, \            ; original GF1 based card
  110.     gusIW                ; AMD InterWave based card
  111.  
  112.  
  113. DATASEG
  114.  
  115. IFDEF    __PASCAL__
  116.     EXTRN    GUS:SoundDevice
  117. ENDIF
  118.  
  119. STRUC    gusInstrument
  120.     D_int    sampleType    ; sampleType
  121.     D_long    sample        ; ptr to sample in GUS mem
  122.     D_long    surround    ; ptr to surround sample in GUS mem / 0
  123.     D_int    length        ; length in bytes
  124.     D_int    loopMode    ; See enum
  125.     D_int    loopNum     ; In loop 1/2 (0 if not looped [anymore])
  126.     D_int    loop1Type    ; See enum
  127.     D_int    loop1Start    ; Offset from beg.
  128.     D_int    loop1End    ; Offset from beg.
  129.     D_int    loop2Type    ; See enum
  130.     D_int    loop2Start    ; Offset from beg.
  131.     D_int    loop2End    ; Offset from beg.
  132. ENDS
  133.  
  134.  
  135.  
  136. ; STATUS BITS:
  137.  
  138. enum    gusStatusBits \
  139.     gsStop = 1, \        ; Stop voice
  140.     gsRetrig = 2, \     ; Retrig note
  141.     gsVolume = 4, \     ; Set volume
  142.     gsFC = 8, \        ; Set FC
  143.     gsSample = 16, \    ; Sample changed
  144.     gsOnOff = 32, \     ; Sample on/off (used for pause)
  145.     gsPanning = 64, \    ; Set panning
  146.     gsMute = 128, \     ; Muted
  147.     gsReleased = 256    ; Note released
  148.  
  149.  
  150.  
  151. STRUC    gusChannel
  152.     D_int    status        ; See enum above
  153.     D_int    inst        ; Number
  154.     D_int    curinst     ; Current instrument playing
  155.     D_int    fc        ; In FC-format
  156.     D_long    frequency    ; In Hz
  157.     D_int    volume        ; 0-64
  158.     D_int    surround    ; Surround flag
  159.     D_int    sampleType    ; See enum
  160.     D_int    loopMode    ; See enum
  161.     D_int    loop1Type    ; See enum
  162.     D_int    loop2Type    ; See enum
  163.     D_long    scurrent    ; Current position for GUS
  164.     D_long    sstart        ; Sample start for GUS
  165.     D_long    send        ; Sample end for GUS
  166.     D_long    l2start     ; Loop 2 start for GUS
  167.     D_long    l2end        ; Loop 2 end for GUS
  168.     D_int    panning     ; Panning position (see enum)
  169.     D_int    panningHW    ; Panning hardware value
  170.     D_int    onoff        ; On / Off switch (DEBUG!)
  171. ENDS
  172.  
  173.  
  174. STRUC    ghb            ; GUS Heap Block
  175.     D_long    next        ; Pointer to next block
  176.     D_long    gusmem        ; Pointer to GUS memory
  177.     D_long    length        ; Length of this block (Rounded to 32 byte border)
  178. ENDS
  179.  
  180. ; lengthFlags:
  181. ;        0 free / allocated
  182.  
  183.  
  184.  
  185. D_int    chancount    ; Amount of channels
  186. D_int    voicesel    ; Voice Select register
  187. D_int    selreg        ; Select Register
  188.  
  189. D_int    mixfreq     ; Mixing frequency
  190. D_int    updRate     ; SD update rate
  191.  
  192. D_int    instpos     ; Instrument to be filled next
  193.  
  194. D_int    muted        ; 0 = unmuted, 1 = muted
  195. D_int    paused        ; 0 = not, 1 = paused
  196. D_int    mastervol    ; Default = max
  197. D_int    masterchanged    ; Overrides channel set volume
  198. D_int    numInsts    ; Max instrument.
  199.  
  200. D_long    memamount    ; Amount of memory on GUS
  201. D_long    memavail    ; Memory available on GUS
  202. D_long    largestblock    ; Largest block of memory on GUS
  203. D_long    gusHeapStart    ; First block of GUS heap
  204. D_long    gusHeap     ; Pointer to GUS heap
  205. D_int    monoFlag    ; Force mono output
  206. D_long    temp        ; Temporary storage
  207. D_int    flag        ; Internal flag
  208. D_int    chansOpen    ; channels open flag
  209. D_int    gusAmp        ; amplification value
  210.  
  211. label channels gusChannel
  212.     rept    32
  213.     gusChannel    ?
  214.     endm
  215.  
  216. D_long    Instruments    ; Pointer to GUS instruments
  217.  
  218.  
  219.  
  220. IDATASEG
  221.  
  222.  
  223. ; If compiling for Pascal, Sound Device name is gusSD, from which the data
  224. ; will be copied to Sound Device GUS, defined in Pascal.
  225.  
  226. IFDEF    __PASCAL__
  227. SDNAM        equ    gusSD
  228. ELSE
  229. SDNAM        equ    GUS
  230. ENDIF
  231.  
  232.  
  233. GLOBAL    SDNAM : SoundDevice
  234.  
  235. ; sdMono or sdStereo or sd16bit, \
  236.  
  237. SDNAM    SoundDevice    < \
  238. 1, \                    ; Called according to tempo
  239. sdUsePort or sdUseOutputMode, \
  240. 220h, 0, 0, \                ; Port, IRQ, DMA
  241. gusAutoType, 2,\            ; Card, num.cards
  242. sdMono or sdStereo or sd16bit, \
  243. ptr_to gusSDName, \
  244. ptr_to gusCardNames, \
  245. 6, ptr_to gusPortAddresses, \
  246. ptr_to gusDetect, \
  247. ptr_to gusInit, \
  248. ptr_to gusClose, \
  249. ptr_to gusGetMixRate, \
  250. ptr_to gusGetMode, \
  251. ptr_to gusOpenChans, \
  252. ptr_to gusCloseChans, \
  253. ptr_to gusClearChans, \
  254. ptr_to gusMute, \
  255. ptr_to gusPause, \
  256. ptr_to gusSetMasterVolume, \
  257. ptr_to gusGetMasterVolume, \
  258. ptr_to gusSetAmplification, \
  259. ptr_to gusGetAmplification, \
  260. ptr_to gusPlaySound, \
  261. ptr_to gusReleaseSound, \
  262. ptr_to gusStopSound, \
  263. ptr_to gusSetRate, \
  264. ptr_to gusGetRate, \
  265. ptr_to gusSetVolume, \
  266. ptr_to gusGetVolume, \
  267. ptr_to gusSetSample, \
  268. ptr_to gusGetSample, \
  269. ptr_to gusSetPosition, \
  270. ptr_to gusGetPosition, \
  271. ptr_to gusGetDirection, \
  272. ptr_to gusSetPanning, \
  273. ptr_to gusGetPanning, \
  274. ptr_to gusMuteChannel, \
  275. ptr_to gusAddSample, \
  276. ptr_to gusRemoveSample, \
  277. ptr_to gusSetUpdRate, \
  278. ptr_to gusStartPlay, \
  279. ptr_to gusPlay >
  280.  
  281. gusSDName    DB    "Gravis Ultrasound Sound Device v4.10",0
  282.  
  283. gusCardNames    DD ptr_to gusName
  284.         DD ptr_to iwName
  285.  
  286. ;gusName         DB "Gravis GF1 (Compatible mode)", 0
  287. ;iwName          DB "AMD InterWave (Enhanced mode)", 0
  288. gusName         DB      "Gravis UltraSound (GF1 Hardware mixing)",0
  289. iwName          DB      "GUS PnP (AMD Interwave Hardware mixing)",0
  290.  
  291. IFDEF __16__
  292. gusPortAddresses DW    210h, 220h, 230h, 240h, 250h, 260h
  293. ELSE
  294. gusPortAddresses DD    210h, 220h, 230h, 240h, 250h, 260h
  295. ENDIF
  296.  
  297. gusIRQAddresses  db 2, 3, 5, 7, 11, 12, 15
  298. gusIRQints     db 71h, 0bh, 0dh, 0fh, 73h, 74h, 77h
  299.  
  300.  
  301. ; gusInterrupt      db 0          ; fuck
  302.  
  303. env        DB "ULTRASND",0
  304. env_iw        DB "INTERWAVE", 0
  305.  
  306. ; Mixing frequencies for channel amounts 14-32
  307.  
  308. chantab dw    44100,41160,38587,36317,34300,32494,30870,29400,28063,26843
  309.     dw    25725,24696,23746,22866,22050,21289,20580,19916,19293
  310.  
  311.  
  312.  
  313. LABEL    voltable    WORD
  314.     dw    01500h,08f10h,09f10h,0ab50h,0af10h,0b970h,0bb50h,0bd30h
  315.     dw    0bf10h,0c880h,0c970h,0ca60h,0cb50h,0cc40h,0cd30h,0ce20h
  316.     dw    0cf10h,0d800h,0d880h,0d8f0h,0d970h,0d9e0h,0da60h,0dad0h
  317.     dw    0db50h,0dbc0h,0dc40h,0dcb0h,0dd30h,0dda0h,0de20h,0de90h
  318.     dw    0df10h,0df80h,0e800h,0e840h,0e880h,0e8b0h,0e8f0h,0e930h
  319.     dw    0e970h,0e9a0h,0e9e0h,0ea20h,0ea60h,0ea90h,0ead0h,0eb10h
  320.     dw    0eb50h,0eb80h,0ebc0h,0ec00h,0ec40h,0ec70h,0ecb0h,0ecf0h
  321.     dw    0ed30h,0ed60h,0eda0h,0ede0h,0ee20h,0ee50h,0ee90h,0eed0h
  322.     dw    0ef00h
  323.  
  324.     ; Louder volume table
  325.  
  326.     IF    0
  327.     dw    01500h,09c10h,0ac10h,0b910h,0bc10h,0bf10h,0c910h,0ca90h
  328.     dw    0cc10h,0cd90h,0cf10h,0d850h,0d910h,0d9d0h,0da90h,0db50h
  329.     dw    0dc10h,0dcd0h,0dd90h,0de50h,0df10h,0dfd0h,0e850h,0e8b0h
  330.     dw    0e910h,0e970h,0e9d0h,0ea30h,0ea90h,0eaf0h,0eb50h,0ebb0h
  331.     dw    0ec10h,0ec70h,0ecd0h,0ed30h,0ed90h,0edf0h,0ee50h,0eeb0h
  332.     dw    0ef10h,0ef70h,0efd0h,0f820h,0f850h,0f880h,0f8b0h,0f8e0h
  333.     dw    0f910h,0f940h,0f970h,0f9a0h,0f9d0h,0fa00h,0fa30h,0fa60h
  334.     dw    0fa90h,0fac0h,0faf0h,0fb20h,0fb50h,0fb80h,0fbb0h,0fbe0h
  335.     dw    0fc00h
  336.     ENDIF
  337.  
  338. ; Panning table for InterWave (pan registers are logarithmic too !!!)
  339. label pantable word
  340.     dw 0FFF0h, 06FD0h, 05FD0h, 05670h, 04FD0h, 04AB0h, 04670h, 042E0h
  341.     dw 03FD0h, 03D20h, 03AB0h, 03870h, 03670h, 034A0h, 032E0h, 03150h
  342.     dw 02FD0h, 02E70h, 02D20h, 02BE0h, 02AB0h, 02990h, 02870h, 02770h
  343.     dw 02670h, 02580h, 024A0h, 023C0h, 022E0h, 02210h, 02150h, 02090h
  344.     dw 01FD0h, 01F20h, 01E70h, 01DC0h, 01D20h, 01C70h, 01BE0h, 01B40h
  345.     dw 01AB0h, 01A20h, 01990h, 01900h, 01870h, 017F0h, 01770h, 016F0h
  346.     dw 01670h, 01600h, 01580h, 01510h, 014A0h, 01430h, 013C0h, 01350h
  347.     dw 012E0h, 01280h, 01210h, 011B0h, 01150h, 010F0h, 01090h, 01030h
  348. label pantablemid word
  349.     dw 00FD0h, 00F70h, 00F20h, 00EC0h, 00E70h, 00E10h, 00DC0h, 00D70h
  350.     dw 00D20h, 00CD0h, 00C70h, 00C30h, 00BE0h, 00B90h, 00B40h, 00AF0h
  351.     dw 00AB0h, 00A60h, 00A20h, 009D0h, 00990h, 00940h, 00900h, 008C0h
  352.     dw 00870h, 00830h, 007F0h, 007B0h, 00770h, 00730h, 006F0h, 006B0h
  353.     dw 00670h, 00640h, 00600h, 005C0h, 00580h, 00550h, 00510h, 004D0h
  354.     dw 004A0h, 00460h, 00430h, 003F0h, 003C0h, 00380h, 00350h, 00320h
  355.     dw 002E0h, 002B0h, 00280h, 00250h, 00210h, 001E0h, 001B0h, 00180h
  356.     dw 00150h, 00120h, 000F0h, 000C0h, 00090h, 00060h, 00030h, 00000h,0
  357.  
  358.  
  359.  
  360. CODESEG
  361.  
  362. ;******* GUS Register Select - Macro ************
  363.  
  364. MACRO    regsel    register
  365.     mov    _dx,[selreg]
  366.     mov    al,register
  367.     out    dx,al
  368. ENDM
  369.  
  370. ;******* GUS-delay subroutine ************
  371.  
  372. PROC    gusdelay NEAR
  373.     push    dx ax
  374.     mov    dx,300h
  375.     rept    8
  376.     in    al,dx
  377.     endm
  378.     pop    ax dx
  379.     ret
  380. ENDP
  381.  
  382.  
  383. ;/***************************************************************************\
  384. ;*
  385. ;* Function:    int gusDetect(int *result)
  386. ;*
  387. ;* Description: Detects Gravis UltraSound and fills in GUS SoundDevice
  388. ;*        structure with appropriate values for port, DMA and IRQ
  389. ;*
  390. ;* Returns:    MIDAS error code.
  391. ;*        1 stored to *result if GUS was detected, 0 if not.
  392. ;*
  393. ;\***************************************************************************/
  394.  
  395. PROC    gusDetect _funct   result : _ptr
  396. USES    _bx
  397.  
  398. ; interwave detect
  399.     cmp    [GUS.cardType],gusAutoType    ; has a card type been set?
  400.     jne    @@cardtypeset            ; if not, detect it
  401.  
  402. ; this finds out if there's INTERWAVE env str set and forces
  403. ; native interwave mode if it exists... dunno about better way to detect ;)
  404.  
  405. IFDEF    __16__
  406.     call    mGetEnv LANG, seg env offset env_iw
  407.     mov    bx,ax
  408.     or    bx,dx
  409. ELSE
  410.     call    mGetEnv LANG, ptr_to env_iw
  411.     test    _ax, _ax
  412. ENDIF
  413.     mov    _dx, gusGF1
  414.     jz    @@plaingus
  415.     mov    _dx, gusIW
  416. @@plaingus:
  417.     mov    [GUS.cardType], _dx
  418. @@cardtypeset:
  419.  
  420. IFDEF    __16__
  421.     call    mGetEnv LANG, seg env offset env
  422.     mov    bx,ax
  423.     or    bx,dx
  424.     jz    @@noGUS
  425.     mov    bx,ax
  426.     mov    es,dx            ; point es:bx to environment string
  427. ELSE
  428.     call    mGetEnv LANG, ptr_to env
  429.     test    eax,eax
  430.     jz    @@noGUS
  431.     mov    ebx,eax
  432. ENDIF
  433.     mov    cl,3                ; 3 digits
  434.     xor    _ax,_ax
  435. @@dloop:
  436.     mov    dl,[_esbx]
  437.     inc    _bx
  438.     sub    dl,"0"
  439.     shl    _ax,4
  440.     add    al,dl
  441.     dec    cl
  442.     jnz    @@dloop
  443.     mov    [GUS.port],_ax
  444. ;
  445. ;     mov     cl, 3             ; now skip three commas
  446. ;@@comma:
  447. ;     mov     al, [_esbx]
  448. ;     inc     _bx
  449. ;     test     al, al          ; if zero the ULTRASND env is wrong
  450. ;     jz     @@noGUS
  451. ;     cmp     al, ','
  452. ;     jnz     @@comma
  453. ;     dec     cl
  454. ;     jnz     @@comma
  455. ;
  456. ;     mov     al,[_esbx]         ; first irq digit (skip comma)
  457. ;     sub     al,"0"
  458. ;     mov     ah, 10
  459. ;     cmp     [byte _esbx+1], ','
  460. ;     jz     @@onedigitirq
  461. ;     imul     ah
  462. ;     add     al,[_esbx+1]         ; second irq digit is necessary
  463. ;     sub     al,"0"
  464. ;@@onedigitirq:
  465. ;     xor     ah, ah
  466. ;     xor     _bx, _bx
  467. ;@@scanirqlist:
  468. ;     cmp     [gusIRQAddresses+_bx], al
  469. ;     jz     @@scanirqfound
  470. ;     inc     _bx
  471. ;     cmp     _bx, 7
  472. ;     jb     @@scanirqlist
  473. ;     jmp     @@noGUS
  474. ;@@scanirqfound:
  475. ;     cmp     al, 2
  476. ;     jnz     @@not2nd
  477. ;     mov     al, 9
  478. ;@@not2nd:
  479. ;     mov     [GUS.IRQ],_ax
  480. ;
  481. ;     mov     al, [gusIRQints+_bx]     ; translate irq to interrupt number
  482. ;     mov     [gusInterrupt], al
  483. ;     inc     bl             ; irq ports start from 0 unlike our irq list
  484. ;     mov     _dx, [GUS.port]
  485. ;     add     dl, 0bh         ; irq control register
  486. ;     mov     al, bl
  487. ;     out     dx, al
  488. ;
  489.  
  490. ; Test if there really is a GUS
  491.  
  492.     add    _ax,103h
  493.     mov    [selreg],_ax            ; Register select (2x0h+103h)
  494.  
  495.     call    gusReset
  496.  
  497.     regsel    44h
  498.     add    _dx,2
  499.     xor    _ax,_ax
  500.     out    dx,al                ; upper bits of address
  501.  
  502.     regsel    43h
  503.     inc    _dx
  504.     xor    _ax,_ax             ; Address 0
  505.     out    dx,ax
  506.     add    _dx,3
  507.     mov    al,055h
  508.     out    dx,al                ; Poke data 1 (55h)
  509.  
  510.     sub    _dx,3
  511.     mov    _ax,1                ; Address 1
  512.     out    dx,ax
  513.     add    _dx,3
  514.     mov    al,0AAh
  515.     out    dx,al                ; Poke data 2 (AAh)
  516.  
  517.     sub    _dx,3
  518.     xor    _ax,_ax             ; Address 0
  519.     out    dx,ax
  520.     add    _dx,3
  521.     in    al,dx                ; Peek data 1
  522.     cmp    al,055h
  523.     jne    @@noGUS
  524.  
  525.     sub    _dx,3
  526.     mov    _ax,1                ; Address 1
  527.     out    dx,ax
  528.     add    _dx,3
  529.     in    al,dx                ; Peek data 2
  530.     cmp    al,0AAh
  531.     je    @@found
  532.  
  533. @@noGUS:
  534.     mov    [GUS.port],0
  535.     xor    _ax,_ax             ; No GUS found
  536.     jmp    @@quit
  537.  
  538. @@found:
  539.     mov    _ax,1                ; GUS found
  540. @@quit:
  541.     LOADPTR es,_bx,[result]
  542.     mov    [_esbx],_ax
  543.     xor    _ax,_ax
  544.     ret
  545. ENDP
  546.  
  547. ;/***************************************************************************\
  548. ;*
  549. ;* Function:    int gusInit(int rate, int mode)
  550. ;*
  551. ;* Description: Initializes the GUS for playing
  552. ;*
  553. ;* Input:    int rate        Mixing rate (no effect on GUS)
  554. ;*        int mode        Mode (see enum) (mono flag only)
  555. ;*
  556. ;* Returns:    MIDAS error code.
  557. ;*
  558. ;\***************************************************************************/
  559.  
  560. PROC    gusInit _funct       rate : _int, mode : _int
  561. USES    _di,_bx
  562.  
  563.     mov    [instpos],1            ; First instrument to be filled
  564.     mov    [numInsts],0            ; No instruments
  565.     mov    [mastervol],64            ; Default master volume
  566.     mov    [masterchanged],0
  567.     mov    [flag],0
  568.     mov    [chansOpen],0
  569.  
  570.     mov    _ax,[mode]
  571.     and    _ax,sdMono            ; AND mono bit
  572.     mov    [monoFlag],_ax            ; 1 if mono, 0 otherwise
  573.  
  574. ;     mov     [monoFlag],0
  575.  
  576.     mov    _ax,[GUS.port]            ; Base address (Set before!)
  577.     add    _ax,103h
  578.     mov    [selreg],_ax            ; Register select (2x0h+103h)
  579.     dec    _ax
  580.     mov    [voicesel],_ax            ; Voice select (2x0h+102h)
  581.  
  582.     call    gusReset            ; Reset GUS
  583.  
  584.     cmp    [GUS.cardType], gusIW
  585.     jnz    @@noiwfound            ; interwave init?
  586.  
  587. ; interwave to enhanced mode (19h bit 0)
  588.     regsel    19h
  589.     add    _dx, 2
  590.     mov    al, 01h             ; set enhanced mode
  591.     out    dx, al
  592. @@noiwfound:
  593.  
  594.     mov    [memamount],0            ; Initial memory amount
  595.     mov    _cx,64                ; Max amount of 256k chunks(IW)
  596.     xor    _bx,_bx             ; Start from 00000h
  597.  
  598. @@memloop:
  599.     regsel    44h
  600.     add    _dx,2
  601.     mov    _ax,_bx
  602.     out    dx,al                ; upper bits of address
  603.  
  604.     regsel    43h
  605.     inc    _dx
  606.     xor    _ax,_ax             ; Address 0
  607.     out    dx,ax
  608.     add    _dx,3
  609.     mov    al,055h
  610.     out    dx,al                ; Poke data 1 (55h)
  611.  
  612.     sub    _dx,3
  613.     mov    _ax,1                ; Address 1
  614.     out    dx,ax
  615.     add    _dx,3
  616.     mov    al,0AAh
  617.     out    dx,al                ; Poke data 2 (AAh)
  618.  
  619.     sub    dx,3
  620.     xor    _ax,_ax             ; Address 0
  621.     out    dx,ax
  622.     add    _dx,3
  623.     in    al,dx                ; Peek data 1
  624.     cmp    al,055h
  625.     jne    @@poiss
  626.  
  627.     sub    _dx,3
  628.     mov    _ax,1                ; Address 1
  629.     out    dx,ax
  630.     add    _dx,3
  631.     in    al,dx                ; Peek data 2
  632.     cmp    al,0AAh
  633.     jne    @@poiss
  634.  
  635.     add    [memamount],256*1024        ; Add amount of memory by 256k
  636.     add    _bx,4                ; Next 256k chunk
  637.     dec    _cx
  638.     jnz    @@memloop
  639.  
  640. @@poiss:                    ; No more memory
  641.     cmp    [memamount],0
  642.     jne    @@memok             ; NO MEMORY!
  643.  
  644.     mov    _ax,errSDFailure        ; NO GUS
  645.     jmp    @@err
  646.  
  647. @@memok:
  648.     mov    eax,[memamount]         ; Initialize mem variables
  649.     mov    [memavail],eax
  650.     mov    [largestblock],eax
  651.  
  652.  
  653. ; Clear the all 32 channels
  654.  
  655.     mov    _dx,[GUS.port]            ; Mixer
  656.     mov    al,3
  657.     out    dx,al                ; Disable Line in & out
  658.  
  659.     regsel    0eh
  660.     add    _dx,2
  661.     mov    al,31 OR 0c0h
  662.     out    dx,al                ; Set number of active
  663.                         ; voices to 32 just for
  664.                         ; sure
  665.  
  666.     mov    _cx,32                ; Number of voices
  667. @@resetloop:
  668.     mov    _dx,[voicesel]            ; Voice Select
  669.     mov    _ax,_cx
  670.     out    dx,al
  671.  
  672.     regsel    0                ; Voice control
  673.     add    _dx,2                ; data low
  674.     mov    al,3                ; Stop voice
  675.     out    dx,al
  676.  
  677.     regsel    9                ; Current Volume
  678.     inc    _dx                ; data high
  679.     mov    _ax,0500h            ; Zero volume
  680.     out    dx,ax
  681.  
  682.     regsel    12                ; Pan Position
  683.     add    _dx,2                ; data low
  684.     mov    al,8                ; Center
  685.     out    dx,al
  686.  
  687.     regsel    13                ; Volume Ramping
  688.     add    _dx,2                ; data low
  689.     mov    al,3                ; disable
  690.     out    dx,al
  691.  
  692.     regsel    6                ; Ramp Rate
  693.     add    _dx,2
  694.     mov    al,3fh                ; Rate
  695.     out    dx,al
  696.  
  697.     cmp    [GUS.cardType], gusIW
  698.     jnz    @@noiwregs
  699.  
  700.     regsel    15h                ;interwave synth mode select
  701.     add    _dx, 2
  702.     mov    al, 22h ; deactivate voice (bit 1), enhanced panning (bit 5)
  703.     out    dx, al
  704.  
  705.     regsel    10h                ;interwave synth upper addr
  706.     add    _dx, 2
  707.     xor    eax, eax
  708.     out    dx, al
  709.  
  710.     regsel    13h                ;interwave synth left offset
  711.     inc    dl
  712.     mov    bx, [pantablemid]
  713.     mov    ax, bx
  714.     out    dx, ax
  715.     regsel    1ch
  716.     inc    dl
  717.     mov    ax, bx
  718.     out    dx, ax
  719.  
  720.     regsel    0ch                ;interwave synth right offset
  721.     inc    dl
  722.     mov    ax, bx
  723.     out    dx, ax
  724.     regsel    1bh
  725.     inc    dl
  726.     mov    ax, bx
  727.     out    dx, ax
  728. @@noiwregs:
  729.     dec    _cx
  730.     jnz    @@resetloop
  731.  
  732.     regsel    4ch                ; RESET
  733.     add    _dx,2
  734.     mov    al,3
  735.     out    dx,al                ; Enable GF1 and DACs
  736.  
  737.     mov    _dx,[GUS.port]
  738.     xor    al,al
  739.     out    dx,al                ; Enable line in and out
  740.  
  741.     call    initHeap            ; Initialize GUS-heap
  742.     test    _ax,_ax
  743.     jne    @@err
  744.  
  745. IFDEF    __16__
  746.     call    memAlloc LANG, MAXSAMPLES * SIZE gusInstrument,\
  747.         seg temp offset temp        ; Alloc room for instruments
  748. ELSE
  749.     call    memAlloc LANG, MAXSAMPLES * SIZE gusInstrument,\
  750.         ptr_to temp            ; Alloc room for instruments
  751. ENDIF
  752.     test    _ax,_ax
  753.     jne    @@err
  754.  
  755.     COPYPTR [Instruments],[temp]
  756.  
  757.     LOADPTR es,_di,[Instruments]
  758. IFDEF    __32__
  759.     push    ds
  760.     pop    es
  761. ENDIF
  762.     xor    _ax,_ax
  763.     mov    _cx,MAXSAMPLES * SIZE gusInstrument
  764.     cld
  765.     rep    stosb                ; Clear instrument datas
  766.     xor    _ax,_ax
  767.     ret
  768.  
  769. @@err:    ERROR    ID_gusInit            ; Heap error
  770.     ret
  771. ENDP
  772.  
  773.  
  774.  
  775. ;/***************************************************************************\
  776. ;*
  777. ;* Function:    gusReset
  778. ;*
  779. ;* Description: Resets the GUS card
  780. ;*
  781. ;* Destroys:    al, dx
  782. ;*
  783. ;* FOR GUS SOUNDDEVICE INTERNAL USE ONLY!
  784. ;*
  785. ;\***************************************************************************/
  786.  
  787. PROC    gusReset NEAR
  788.     regsel    4ch                ; RESET
  789.     add    _dx,2
  790.     xor    al,al
  791.     out    dx,al                ; RESET!
  792.  
  793.     call    gusdelay
  794.     call    gusdelay
  795.  
  796.     mov    al,1
  797.     out    dx,al                ; Enable GF1
  798.  
  799.     call    gusdelay
  800.     call    gusdelay
  801.     ret
  802. ENDP
  803.  
  804. ;/***************************************************************************\
  805. ;*
  806. ;* Function:    int gusClose()
  807. ;*
  808. ;* Description: Closes up the GUS.
  809. ;*
  810. ;* Returns:    MIDAS error code.
  811. ;*
  812. ;\***************************************************************************/
  813.  
  814. PROC    gusClose _funct
  815. USES    _bx
  816.  
  817.     call    gusReset
  818.  
  819.     regsel    19h                ; interwave to gus mode
  820.     add    _dx, 2
  821.     xor    al, al                ; set gus compatible mode
  822.     out    dx, al
  823.  
  824.     mov    _dx,[GUS.port]            ; Mixer
  825.     xor    al,al
  826.     out    dx,al                ; Enable Line in & out
  827.  
  828.     call    freeHeap
  829.     test    _ax,_ax
  830.     jnz    @@err
  831.  
  832.     call    memFree LANG, [Instruments]    ; Free instruments
  833.     test    _ax,_ax
  834.     jnz    @@err
  835.  
  836.     mov    [instpos],1            ; Flush instruments
  837.     ret                    ; ax already 0
  838.  
  839. @@err:    ERROR    ID_gusClose
  840.     ret
  841. ENDP
  842.  
  843.  
  844. ;/***************************************************************************\
  845. ;*
  846. ;* Function:    int gusGetMixRate(int *rate)
  847. ;*
  848. ;* Description: Returns the mixing rate of the SD
  849. ;*
  850. ;* Returns:    MIDAS error code.
  851. ;*        Mixing rate is written to *rate.
  852. ;*
  853. ;\***************************************************************************/
  854.  
  855. PROC    gusGetMixRate _funct       rate : _ptr
  856. USES    _bx
  857.  
  858.     mov    _ax,[mixfreq]             ; Get mixing rate
  859.     LOADPTR es,_bx,[rate]
  860.     mov    [_esbx],_ax
  861.     xor    _ax,_ax              ; Can't fail
  862.     ret
  863. ENDP
  864.  
  865.  
  866.  
  867. ;/***************************************************************************\
  868. ;*
  869. ;* Function:    int gusGetMode(int *mode)
  870. ;*
  871. ;* Description: Returns the output mode
  872. ;*
  873. ;* Returns:    MIDAS error code.
  874. ;*        Output mode is written to *mode.
  875. ;*
  876. ;\***************************************************************************/
  877.  
  878. PROC    gusGetMode    _funct       mode : _ptr
  879. USES    _bx
  880.  
  881.     mov    _ax,sd16bit
  882.     mov    _bx,2
  883.     sub    _bx,[monoFlag]            ; 1 if mono (=sdMono)
  884.                         ; 2 if not (=sdStereo)
  885.     or    _ax,_bx
  886.     LOADPTR es,_bx,[mode]
  887.     mov    [_esbx],_ax
  888.     xor    _ax,_ax             ; Can't fail
  889.     ret
  890. ENDP
  891.  
  892.  
  893. ;/***************************************************************************\
  894. ;*
  895. ;* Function:    int gusOpenChans(int chans)
  896. ;*
  897. ;* Description: Opens channels from the GUS
  898. ;*
  899. ;* Input:    int chans        Number of channels to open
  900. ;*
  901. ;* Returns:    MIDAS error code.
  902. ;*
  903. ;\***************************************************************************/
  904.  
  905. PROC    gusOpenChans _funct    chans : _int
  906. USES    _si,_di,_bx
  907.  
  908.     mov    [gusAmp],64
  909.  
  910.  
  911.     mov    _bx,[chans]
  912.     mov    [chancount],_bx
  913.  
  914.     mov    [muted],0
  915.     mov    [paused],0
  916.  
  917. IFNDEF NOSTEREO
  918.     cmp    [mEnableSurround],0
  919.     je    @@nsurr
  920.     add    _bx,_bx
  921.     cmp    _bx,32
  922.     ja    @@err
  923. @@nsurr:
  924. ENDIF
  925.     cmp    _bx,14
  926.     jae    @@okei
  927.     mov    _bx,14                ; At least 14 channels open
  928. @@okei:
  929.     mov    _cx,_bx
  930.  
  931.     sub    _bx,14
  932.     add    _bx,_bx
  933.     mov    bx,[chantab+_bx]           ; Take the mixing rate
  934.  
  935.     cmp    [GUS.cardType], gusIW
  936.     jnz    @@noiwmixrate
  937.     mov    _bx, 44100               ; interwave is always 44.1kHz
  938. @@noiwmixrate:
  939.     mov    [mixfreq],_bx
  940.  
  941.     regsel    0eh
  942.     add    _dx,2
  943.     mov    _ax,_cx
  944.     dec    _ax                ; Amount-1
  945.     or    al,0c0h
  946.     out    dx,al
  947.  
  948.     mov    _ax,ds
  949.     mov    es,_ax
  950.     mov    _di,offset channels
  951.     xor    al,al
  952.     cld
  953.     mov    _cx,size gusChannel*32
  954.     rep    stosb                ; Clear channel blocks
  955.  
  956.     mov    _cx,[chans]            ; to the table
  957.     xor    _bx,_bx             ; Start from channel 0
  958. @@panloop:
  959.     mov    _dx,[voicesel]            ; Voice Select
  960.     mov    _ax,[chans]
  961.     sub    _ax,_cx
  962.     out    dx,al
  963.  
  964.     regsel    12                ; Pan Position
  965.     add    _dx,2                ; data low
  966.  
  967.     mov    [_bx+channels.panning],panMiddle ; Panning position
  968.  
  969.     mov    al,8                ; Middle
  970.     out    dx,al
  971.  
  972.     cmp    [GUS.cardType], gusIW
  973.     jnz    @@noiwregs
  974.  
  975. ; interwave synth mode select
  976.     regsel    15h
  977.     add    _dx, 2
  978.     mov    al, 20h     ; activate voice, select enhanced panning
  979.     out    dx, al
  980. ; interwave synth right offset ( bigger blocks sound )
  981.     regsel    0ch
  982.     inc    dl
  983.     mov    ax, [pantablemid]
  984.     out    dx, ax
  985.     regsel    1bh            ; right offset fine
  986.     inc    dl
  987.     mov    ax, [pantablemid]
  988.     out    dx, ax
  989. ; interwave synth left offset
  990.     regsel    13h            ; left offset
  991.     inc    dl
  992.     mov    ax, [pantablemid]
  993.     out    dx, ax
  994.     regsel    1ch            ; left offset fine
  995.     inc    dl
  996.     mov    ax, [pantablemid]
  997.     out    dx, ax
  998.  
  999. @@noiwregs:
  1000.  
  1001.     mov    [_bx+channels.status],gsStop
  1002.     cmp    [mEnableSurround],0
  1003.     je    @@nss
  1004.  
  1005.     mov    _ax,[chancount]
  1006.     imul    _ax,_ax,size gusChannel     ; Get surround chan
  1007.     mov    _si,_ax
  1008.     add    _si,_bx
  1009.     mov    [_si+channels.status],gsMute OR gsStop
  1010.  
  1011. @@nss:    add    _bx,SIZE gusChannel
  1012.     dec    _cx
  1013.     jnz    @@panloop
  1014.  
  1015.     mov    [chansOpen],1
  1016.  
  1017.     mov    _dx,[GUS.port]
  1018.     xor    al,al
  1019.     out    dx,al                ; Enable line in and out
  1020.  
  1021.     call    gusMute LANG, 0
  1022.     test    _ax,_ax
  1023.     jnz    @@err2
  1024.     ret
  1025.  
  1026. @@err:    mov    _ax,errNoChannels        ; Too much channels
  1027. @@err2: ERROR    ID_gusOpenChans
  1028.     ret
  1029. ENDP
  1030.  
  1031.  
  1032. ;/***************************************************************************\
  1033. ;*
  1034. ;* Function:    int gusCloseChans()
  1035. ;*
  1036. ;* Description: Closes channels from the GUS
  1037. ;*
  1038. ;* Returns:    MIDAS error code.
  1039. ;*
  1040. ;\***************************************************************************/
  1041.  
  1042. PROC    gusCloseChans     _funct
  1043. USES    _bx
  1044.  
  1045.     call    gusClearChans LANG
  1046.     mov    [chansOpen],0
  1047.     mov    [chancount],0
  1048.     xor    _ax,_ax         ; Can't fail
  1049.     ret
  1050. ENDP
  1051.  
  1052.  
  1053. ;/***************************************************************************\
  1054. ;*
  1055. ;* Function:    int gusClearChans()
  1056. ;*
  1057. ;* Description: Clears the channels from the GUS
  1058. ;*
  1059. ;* Returns:    MIDAS error code.
  1060. ;*
  1061. ;\***************************************************************************/
  1062.  
  1063. PROC    gusClearChans     _funct
  1064. USES    _si,_bx
  1065.  
  1066.     xor    _bx,_bx
  1067.     mov    _cx,[chancount]
  1068. @@clloop:
  1069.     mov    _dx,[voicesel]            ; Voice Select
  1070.     mov    _ax,[chancount]
  1071.     sub    _ax,_cx
  1072.     out    dx,al
  1073.  
  1074.     regsel    0                ; Voice control
  1075.     add    _dx,2
  1076.     mov    al,3
  1077.     out    dx,al                ; Stop sound
  1078.  
  1079.     call    gusdelay
  1080.  
  1081.     out    dx,al                ; Stop sound
  1082.  
  1083.     regsel    12                ; Pan Position
  1084.     add    _dx,2                ; data low
  1085.  
  1086.     mov    [_bx+channels.panning],panMiddle ; Panning position
  1087.     mov    [_bx+channels.inst],0        ; No instrument
  1088.     mov    [_bx+channels.curinst],0    ; No instrument
  1089.     mov    [_bx+channels.status],gsStop
  1090.  
  1091.     mov    al,8                ; Middle
  1092.     out    dx,al
  1093.  
  1094.     cmp    [GUS.cardType], gusIW
  1095.     jnz    @@noiwregs
  1096. ; interwave synth mode select
  1097.     regsel    0ch
  1098.     add    dl, 2
  1099.     mov    al, 2            ; de-active channel
  1100.     out    dx, al
  1101. ; interwave synth right offset
  1102.     regsel    0ch
  1103.     inc    dl
  1104.     mov    ax, [pantablemid]
  1105.     out    dx, ax
  1106.     regsel    1bh            ; right offset fine
  1107.     inc    dl
  1108.     mov    ax, [pantablemid]
  1109.     out    dx, ax
  1110. ; interwave synth left offset
  1111.     regsel    13h            ; left offset
  1112.     inc    dl
  1113.     mov    ax, [pantablemid]
  1114.     out    dx, ax
  1115.     regsel    1ch            ; left offset fine
  1116.     inc    dl
  1117.     mov    ax, [pantablemid]
  1118.     out    dx, ax
  1119. @@noiwregs:
  1120.  
  1121.  
  1122. IFNDEF NOSTEREO
  1123.     cmp    [mEnableSurround],0
  1124.     je    @@nss
  1125.  
  1126.     mov    _ax,[chancount]
  1127.     imul    _ax,_ax,size gusChannel     ; Get surround chan
  1128.     mov    _si,_ax
  1129.     add    _si,_bx
  1130.     mov    [_si+channels.status],gsMute OR gsStop
  1131.  
  1132.     mov    _dx,[voicesel]            ; Voice Select
  1133.     mov    _ax,[chancount]
  1134.     add    _ax,_ax             ; Surround channel
  1135.     sub    _ax,_cx
  1136.     out    dx,al
  1137.  
  1138.     regsel    0                ; Voice control
  1139.     add    _dx,2
  1140.     mov    al,3
  1141.     out    dx,al                ; Stop sound
  1142.  
  1143.     call    gusdelay
  1144.  
  1145.     out    dx,al                ; Stop sound
  1146.  
  1147. @@nss:
  1148. ENDIF
  1149.     add    _bx,SIZE gusChannel
  1150.     dec    _cx
  1151.     jnz    @@clloop
  1152.     xor    _ax,_ax             ; Can't fail
  1153.     ret
  1154. ENDP
  1155.  
  1156.  
  1157. ;/***************************************************************************\
  1158. ;*
  1159. ;* Function:    int gusMute(ushort mute)
  1160. ;*
  1161. ;* Description: Mutes/unmutes GUS Sound Device
  1162. ;*
  1163. ;* Input:    int mute        UnMute = 0 / Mute = 1
  1164. ;*
  1165. ;* Returns:    MIDAS error code.
  1166. ;*
  1167. ;\***************************************************************************/
  1168.  
  1169. PROC    gusMute _funct       mute : _int
  1170. USES    _bx
  1171.  
  1172.     mov    _ax,[mute]
  1173.     cmp    [muted],_ax
  1174.     je    @@done                ; Already at that state
  1175.     mov    [muted],_ax
  1176.     mov    bl,1                ; Enable GF1 (Disable DACs)
  1177.     test    _ax,_ax
  1178.     jnz    @@mute
  1179.     mov    bl,3                ; Enable DACs (unmute)
  1180. @@mute: cli
  1181.     regsel    4ch                ; RESET
  1182.     add    _dx,2
  1183.     mov    al,bl
  1184.     out    dx,al
  1185.     sti
  1186. @@done: xor    _ax,_ax             ; Can't fail
  1187.     ret
  1188. ENDP
  1189.  
  1190.  
  1191.  
  1192. ;/***************************************************************************\
  1193. ;*
  1194. ;* Function:    int gusPause(ushort pause)
  1195. ;*
  1196. ;* Description: Pauses/unpauses GUS SD
  1197. ;*
  1198. ;* Input:    int pause        Unpause = 0 / Pause = 1
  1199. ;*
  1200. ;* Returns:    MIDAS error code.
  1201. ;*
  1202. ;\***************************************************************************/
  1203.  
  1204. PROC    gusPause _funct     pause : _int
  1205. USES    _bx
  1206.  
  1207.     mov    _ax,[pause]
  1208.     cmp    [paused],_ax
  1209.     je    @@done                ; Already at that state
  1210.     mov    [paused],_ax
  1211.     test    _ax,_ax
  1212.     jnz    @@pause
  1213.  
  1214.     xor    _cx,_cx
  1215.     xor    _bx,_bx
  1216. @@chloop:
  1217.     test    [_bx+channels.status],gsOnOff
  1218.     jz    @@off
  1219.  
  1220.     cli
  1221.     mov    _dx,[voicesel]            ; Select voice
  1222.     mov    _ax,_cx
  1223.     out    dx,al
  1224.  
  1225.     regsel    0
  1226.     add    _dx,2
  1227.     mov    _ax,[_bx+channels.loopMode]
  1228.     cmp    _ax,sdLoopNone
  1229.     je    @@noloop
  1230.     cmp    _ax,sdLoopAmigaNone
  1231.     je    @@noloop
  1232.     cmp    _ax,sdLoopAmiga
  1233.     je    @@loopuni
  1234.  
  1235.     test    [_bx+channels.status],gsReleased
  1236.     jnz    @@loop2
  1237.  
  1238.     cmp    [_bx+channels.loop1Type],loopUnidir
  1239.     je    @@loopuni
  1240.     jmp    @@loopbidi
  1241.  
  1242. @@loop2:
  1243.     cmp    [_bx+channels.loop2Type],loopNone
  1244.     je    @@noloop
  1245.     cmp    [_bx+channels.loop2Type],loopBidir
  1246.     je    @@loopbidi
  1247.  
  1248. @@loopuni:
  1249.     mov    al,8
  1250.     jmp    @@loopok
  1251.  
  1252. @@loopbidi:
  1253.     mov    al,24
  1254.     jmp    @@loopok
  1255.  
  1256. @@noloop:
  1257.     xor    al,al
  1258.  
  1259. @@loopok:
  1260.     out    dx,al
  1261.     sti
  1262.  
  1263. @@off:    add    _bx,SIZE gusChannel
  1264.     inc    _cx
  1265.     cmp    _cx,32
  1266.     jne    @@chloop
  1267.     jmp    @@done
  1268.  
  1269. @@pause:
  1270.     xor    _cx,_cx
  1271.     xor    _bx,_bx
  1272. @@chloop2:
  1273.     cli
  1274.     mov    _dx,[voicesel]            ; Select voice
  1275.     mov    _ax,_cx
  1276.     out    dx,al
  1277.  
  1278.     regsel    80h
  1279.     add    _dx,2
  1280.     in    al,dx
  1281.     sti
  1282.  
  1283.     and    _ax,1                ; Voice on / off
  1284.     xor    al,1                ; To active high
  1285.     shl    al,5                ; to bit 5
  1286.     and    [_bx+channels.status],NOT gsOnOff
  1287.     or    [_bx+channels.status],_ax
  1288.  
  1289.     cli
  1290.     regsel    0
  1291.     add    _dx,2
  1292.     mov    al,3
  1293.     out    dx,al                ; Stop
  1294.     sti
  1295.  
  1296.     add    _bx,SIZE gusChannel
  1297.     inc    _cx
  1298.     cmp    _cx,32
  1299.     jne    @@chloop2
  1300.  
  1301. @@done: xor    _ax,_ax
  1302.     ret
  1303. ENDP
  1304.  
  1305.  
  1306.  
  1307. ;/***************************************************************************\
  1308. ;*
  1309. ;* Function:    int gusSetMasterVolume(uchar master)
  1310. ;*
  1311. ;* Description: Sets the master volume for the GUS
  1312. ;*
  1313. ;* Input:    int master        new master volume (0-64)
  1314. ;*
  1315. ;* Returns:    MIDAS error code.
  1316. ;*
  1317. ;\***************************************************************************/
  1318.  
  1319. PROC    gusSetMasterVolume _funct    master : _int
  1320. USES    _bx
  1321.  
  1322.     mov    _ax,[master]
  1323.     cmp    [mastervol],_ax
  1324.     je    @@done                ; Already at that value
  1325.     mov    [mastervol],_ax
  1326.     mov    [masterchanged],1
  1327. @@done: xor    _ax,_ax             ; Can't fail
  1328.     ret
  1329. ENDP
  1330.  
  1331.  
  1332.  
  1333.  
  1334. ;/***************************************************************************\
  1335. ;*
  1336. ;* Function:    int gusGetMasterVolume(uchar *masterVolume)
  1337. ;*
  1338. ;* Description: Sets the master volume for the GUS
  1339. ;*
  1340. ;* Input:    int *masterVolume    pointer to master volume (0-64)
  1341. ;*
  1342. ;* Returns:    MIDAS error code. Master volume is written to *masterVolume.
  1343. ;*
  1344. ;\***************************************************************************/
  1345.  
  1346. PROC    gusGetMasterVolume _funct    masterVolume : _ptr
  1347. USES    _bx
  1348.  
  1349.     mov    _ax,[mastervol]
  1350.     LOADPTR es,_bx,[masterVolume]
  1351.     mov    [_esbx],_ax
  1352.     xor    _ax,_ax         ; Can't fail
  1353.     ret
  1354. ENDP
  1355.  
  1356.  
  1357.  
  1358.  
  1359. ;/***************************************************************************\
  1360. ;*
  1361. ;* Function:    int gusSetAmplification(unsigned amplification);
  1362. ;*
  1363. ;* Description: Sets amplification level - does nothing except stores the
  1364. ;*        value for gusGetAmplification().
  1365. ;*
  1366. ;* Input:    unsigned amplification    amplification level - 64 = normal
  1367. ;*
  1368. ;* Returns:    MIDAS error code.
  1369. ;*
  1370. ;\***************************************************************************/
  1371.  
  1372. PROC    gusSetAmplification _funct    amplification : _int
  1373.  
  1374.     mov    _ax,[amplification]
  1375.     mov    [gusAmp],_ax
  1376.     xor    _ax,_ax         ; Can't fail
  1377.     ret
  1378. ENDP
  1379.  
  1380.  
  1381.  
  1382.  
  1383. ;/***************************************************************************\
  1384. ;*
  1385. ;* Function:    int gusGetAmplification(unsigned *amplification);
  1386. ;*
  1387. ;* Description: Gets amplification level.
  1388. ;*
  1389. ;* Input:    unsigned *amplification   pointer to amplification level
  1390. ;*
  1391. ;* Returns:    MIDAS error code. Amplification level is written to
  1392. ;*        *amplification.
  1393. ;*
  1394. ;\***************************************************************************/
  1395.  
  1396. PROC    gusGetAmplification _funct    amplification : _ptr
  1397. USES    _bx
  1398.  
  1399.     mov    _ax,[gusAmp]
  1400.     LOADPTR es,_bx,[amplification]
  1401.     mov    [_esbx],_ax
  1402.     xor    _ax,_ax         ; Can't fail
  1403.     ret
  1404. ENDP
  1405.  
  1406.  
  1407.  
  1408.  
  1409. ;/***************************************************************************\
  1410. ;*
  1411. ;* Function:    int gusPlaySound(int chan, ulong freq)
  1412. ;*
  1413. ;* Description: Starts a sound with a frequency
  1414. ;*
  1415. ;* Input:    int chan        Channel number
  1416. ;*        ulong freq        Playing frequency
  1417. ;*
  1418. ;* Returns:    MIDAS error code.
  1419. ;*
  1420. ;\***************************************************************************/
  1421. PROC    gusPlaySound _funct    chan : _int, freq : dword
  1422. USES    _si,_bx
  1423. LOCAL    fc : _int
  1424.  
  1425.     mov    _bx,[chan]
  1426.     cmp    [chancount],_bx
  1427.     jle    @@errchan
  1428.  
  1429.     imul    _bx,_bx,size gusChannel     ; Get channel block
  1430.  
  1431.     mov    eax,[freq]
  1432.     cmp    [_bx+channels.frequency],eax
  1433.     je    @@nochange
  1434.     mov    [_bx+channels.frequency],eax
  1435.  
  1436.     shl    eax,10
  1437.     xor    edx,edx
  1438. IFDEF    __16__
  1439.     xor    ecx,ecx
  1440. ENDIF
  1441.     mov    _cx,[mixfreq]            ; GUS freq = frequency / mixing rate
  1442.     idiv    ecx
  1443.     and    al,0feh             ; Bit 0 unused
  1444.     mov    [_bx+channels.fc],_ax
  1445.     mov    [fc],_ax
  1446.     or    [_bx+channels.status],gsFC
  1447.  
  1448. @@nochange:
  1449.     mov    _dx,[_bx+channels.inst]     ; Instrument number
  1450.     test    _dx,_dx
  1451.     jz    @@errinst            ; No instrument?
  1452.     cmp    [numInsts],_dx
  1453.     jb    @@errinst
  1454.  
  1455.     dec    _dx                ; Table starts from 1
  1456.     imul    _dx,_dx,SIZE gusInstrument
  1457.  
  1458.     LOADPTR es,_si,[Instruments]
  1459.     add    _si,_dx
  1460.     cmp    [_essi+gusInstrument.length],0
  1461.     je    @@stop
  1462.  
  1463.     mov    ecx,[_essi+gusInstrument.sample] ; Start address
  1464.     mov    [_bx+channels.scurrent],ecx    ; Tell start position to GUS
  1465.     and    [_bx+channels.status],NOT (gsStop OR gsReleased)
  1466.     or    [_bx+channels.status],gsRetrig
  1467.  
  1468.     mov    [_bx+channels.onoff],1
  1469.  
  1470. IFNDEF NOSTEREO
  1471.     cmp    [mEnableSurround],0
  1472.     je    @@quit
  1473.  
  1474.     mov    _bx,[chan]
  1475.     add    _bx,[chancount]
  1476.     imul    _bx,_bx,size gusChannel       ; Get channel block
  1477.  
  1478.     mov    eax,[freq]
  1479.     cmp    [_bx+channels.frequency],eax
  1480.     je    @@nocha
  1481.     mov    [_bx+channels.frequency],eax
  1482.  
  1483.     mov    _ax,[fc]
  1484.     mov    [_bx+channels.fc],_ax
  1485.     or    [_bx+channels.status],gsFC
  1486.  
  1487. @@nocha:
  1488.     mov    ecx,[_essi+gusInstrument.surround] ; Start address
  1489.     test    ecx,ecx
  1490.     jnz    @@ok2
  1491.     mov    ecx,[_essi+gusInstrument.sample] ; Start address
  1492. @@ok2:    mov    [_bx+channels.scurrent],ecx    ; Tell start position to GUS
  1493.     and    [_bx+channels.status],NOT (gsStop OR gsReleased)
  1494.     or    [_bx+channels.status],gsRetrig
  1495.     mov    [_bx+channels.onoff],1
  1496. ENDIF
  1497. @@quit:
  1498.     xor    _ax,_ax
  1499.     ret
  1500.  
  1501. @@stop: call    gusStopSound LANG, [chan]
  1502.     ret
  1503.  
  1504. @@errchan:
  1505.     mov    _ax,errInvalidChanNumber
  1506.     jmp    @@err
  1507. @@errinst:
  1508.     mov    _ax,errInvalidSampleHandle
  1509. @@err:    ERROR    ID_gusPlaySound
  1510.     ret
  1511.  
  1512. ENDP
  1513.  
  1514.  
  1515. ;/***************************************************************************\
  1516. ;*
  1517. ;* Function:    int gusReleaseSound(int chan)
  1518. ;*
  1519. ;* Description: Releases a sound in channel
  1520. ;*
  1521. ;* Input:    int chan        Channel number
  1522. ;*
  1523. ;* Returns:    MIDAS error code.
  1524. ;*
  1525. ;\***************************************************************************/
  1526.  
  1527. PROC    gusReleaseSound _funct       chan : _int
  1528. USES    _bx
  1529.  
  1530.     mov    _bx,[chan]
  1531.     cmp    [chancount],_bx
  1532.     jle    @@errchan
  1533.  
  1534.     imul    _bx,_bx,size gusChannel     ; Get channel block
  1535.     or    [_bx+channels.status],gsReleased
  1536.     xor    _ax,_ax
  1537.     ret
  1538.  
  1539. @@errchan:
  1540.     mov    _ax,errInvalidChanNumber
  1541.     ERROR    ID_gusReleaseSound
  1542.     ret
  1543.  
  1544.  
  1545. ENDP
  1546.  
  1547. ;/***************************************************************************\
  1548. ;*
  1549. ;* Function:    int gusStopSound(int chan)
  1550. ;*
  1551. ;* Description: Stops sound on a channel
  1552. ;*
  1553. ;* Input:    int chan        Channel number
  1554. ;*
  1555. ;* Returns:    MIDAS error code.
  1556. ;*
  1557. ;\***************************************************************************/
  1558.  
  1559. PROC    gusStopSound _funct    chan : _int
  1560. USES    _bx
  1561.  
  1562.     mov    _bx,[chan]
  1563.     cmp    [chancount],_bx
  1564.     jle    @@err
  1565.  
  1566.     imul    _bx,_bx,size gusChannel     ; Channel block
  1567.  
  1568.     and    [_bx+channels.status],NOT gsRetrig
  1569.     or    [_bx+channels.status],gsStop
  1570.  
  1571. IFNDEF NOSTEREO
  1572.     cmp    [mEnableSurround],0
  1573.     je    @@quit
  1574.  
  1575.     mov    _bx,[chan]
  1576.     add    _bx,[chancount]
  1577.     imul    _bx,_bx,size gusChannel     ; Channel block
  1578.  
  1579.     and    [_bx+channels.status],NOT gsRetrig
  1580.     or    [_bx+channels.status],gsStop
  1581. ENDIF
  1582. @@quit: xor    _ax,_ax
  1583.     ret
  1584.  
  1585. @@err:    mov    _ax,errInvalidChanNumber
  1586.     ERROR    ID_gusStopSound
  1587.     ret
  1588. ENDP
  1589.  
  1590.  
  1591. ;/***************************************************************************\
  1592. ;*
  1593. ;* Function:    int gusSetRate(int chan, ulong freq)
  1594. ;*
  1595. ;* Description: Sets the playing rate for a channel
  1596. ;*
  1597. ;* Input:    int chan        Channel number
  1598. ;*        ulong freq        New playing frequency
  1599. ;*
  1600. ;* Returns:    MIDAS error code.
  1601. ;*
  1602. ;\***************************************************************************/
  1603.  
  1604. PROC    gusSetRate _funct     chan : _int, freq : dword
  1605. USES    _bx
  1606.  
  1607.     mov    _bx,[chan]
  1608.     cmp    [chancount],_bx
  1609.     jle    @@err
  1610.  
  1611.     imul    _bx,_bx,size gusChannel
  1612.  
  1613.     mov    eax,[freq]
  1614.     cmp    [_bx+channels.frequency],eax
  1615.     je    @@quit
  1616.     mov    [_bx+channels.frequency],eax
  1617.  
  1618.     shl    eax,10
  1619.     xor    edx,edx
  1620. IFDEF    __16__
  1621.     xor    ecx,ecx
  1622. ENDIF
  1623.     mov    _cx,[mixfreq]            ; GUS freq = frequency / mixing rate
  1624.     idiv    ecx
  1625.     and    al,0feh             ; bit 0 unused
  1626.     mov    [_bx+channels.fc],_ax
  1627.     or    [_bx+channels.status],gsFC
  1628.  
  1629. IFNDEF NOSTEREO
  1630.     cmp    [mEnableSurround],0
  1631.     je    @@quit
  1632.  
  1633.     mov    _bx,[chan]
  1634.     add    _bx,[chancount]
  1635.     imul    _bx,_bx,size gusChannel
  1636.  
  1637.     mov    [_bx+channels.fc],_ax
  1638.     mov    eax,[freq]
  1639.     mov    [_bx+channels.frequency],eax
  1640.     or    [_bx+channels.status],gsFC
  1641. ENDIF
  1642. @@quit: xor    _ax,_ax
  1643.     ret
  1644.  
  1645. @@err:    mov    _ax,errInvalidChanNumber
  1646.     ERROR    ID_gusSetRate
  1647.     ret
  1648. ENDP
  1649.  
  1650.  
  1651. ;/***************************************************************************\
  1652. ;*
  1653. ;* Function:    int gusGetRate(int chan, ulong *freq)
  1654. ;*
  1655. ;* Description: Returns the playing rate for a channel
  1656. ;*
  1657. ;* Input:    int chan        Channel number
  1658. ;*        ulong *freq        Pointer to frequency
  1659. ;*
  1660. ;* Returns:    MIDAS error code.
  1661. ;*
  1662. ;\***************************************************************************/
  1663.  
  1664. PROC    gusGetRate    _funct       chan : _int, freq : _ptr
  1665. USES    _bx
  1666.  
  1667.     mov    _bx,[chan]
  1668.     cmp    [chancount],_bx
  1669.     jle    @@err
  1670.  
  1671.     cli
  1672.     mov    _dx,[voicesel]             ; Select voice
  1673.     mov    _ax,_bx
  1674.     out    dx,al
  1675.  
  1676.     regsel    80h                ; Voice control
  1677.     add    _dx,2
  1678.     in    al,dx
  1679.     sti
  1680.  
  1681.     test    al,1
  1682.     jnz    @@stopped            ; Is sound on?
  1683.  
  1684.     mov    _bx,[chan]
  1685.     imul    _bx,_bx,size gusChannel
  1686.  
  1687.     mov    eax,[_bx+channels.frequency]
  1688.     LOADPTR es,_bx,[freq]
  1689.     mov    [_esbx],eax
  1690.     xor    _ax,_ax
  1691.     ret
  1692.  
  1693. @@stopped:
  1694.     LOADPTR es,_bx,[freq]
  1695.     mov    [dword _esbx],0
  1696.     xor    _ax,_ax
  1697.     ret
  1698.  
  1699. @@err:    mov    _ax,errInvalidChanNumber
  1700.     ERROR    ID_gusGetRate
  1701.     ret
  1702. ENDP
  1703.  
  1704.  
  1705.  
  1706. ;/***************************************************************************\
  1707. ;*
  1708. ;* Function:    int gusSetVolume(int chan, int volume)
  1709. ;*
  1710. ;* Description: Sets the volume for a channel
  1711. ;*
  1712. ;* Input:    int chan        Channel number
  1713. ;*        int volume        New playing volume
  1714. ;*
  1715. ;* Returns:    MIDAS error code.
  1716. ;*
  1717. ;\***************************************************************************/
  1718. PROC    gusSetVolume    _funct       chan : _int, vol : _int
  1719. USES    _bx
  1720.  
  1721.     mov    _ax,[vol]
  1722.     cmp    _ax,64
  1723.     jbe    @@not64             ; Max volume = 64
  1724.     mov    _ax,64
  1725. @@not64:
  1726.     mov    _bx,[chan]
  1727.     cmp    [chancount],_bx
  1728.     jle    @@err
  1729.  
  1730.     imul    _bx,_bx,size gusChannel
  1731.  
  1732.     cmp    [_bx+channels.volume],_ax
  1733.     je    @@quit
  1734.  
  1735.     mov    [_bx+channels.volume],_ax
  1736.     or    [_bx+channels.status],gsVolume
  1737.  
  1738. IFNDEF NOSTEREO
  1739.     cmp    [mEnableSurround],0
  1740.     je    @@quit
  1741.  
  1742.     mov    _bx,[chan]
  1743.     add    _bx,[chancount]
  1744.     imul    _bx,_bx,size gusChannel
  1745.  
  1746.     mov    [_bx+channels.volume],_ax
  1747.     or    [_bx+channels.status],gsVolume
  1748. ENDIF
  1749. @@quit: xor    _ax,_ax
  1750.     ret
  1751.  
  1752. @@err:    mov    _ax,errInvalidChanNumber
  1753.     ERROR    ID_gusSetVolume
  1754.     ret
  1755.  
  1756. ENDP
  1757.  
  1758.  
  1759. ;/***************************************************************************\
  1760. ;*
  1761. ;* Function:    int gusGetVolume(int chan, int *volume)
  1762. ;*
  1763. ;* Description: Sets the volume for a channel
  1764. ;*
  1765. ;* Input:    int chan        Channel number
  1766. ;*        int *volume        Pointer to volume
  1767. ;*
  1768. ;* Returns:    MIDAS error code. Playing volume is written to *volume
  1769. ;*
  1770. ;\***************************************************************************/
  1771.  
  1772. PROC    gusGetVolume    _funct       chan : _int, volume : _ptr
  1773. USES    _bx
  1774.  
  1775.     mov    _bx,[chan]
  1776.     cmp    [chancount],_bx
  1777.     jle    @@err
  1778.  
  1779.     imul    _bx,_bx,size gusChannel
  1780.  
  1781.     mov    _ax,[_bx+channels.volume]
  1782.     LOADPTR es,_bx,[volume]
  1783.     mov    [_esbx],_ax
  1784.  
  1785.     xor    _ax,_ax
  1786.     jmp    @@done
  1787.  
  1788. @@err:    mov    _ax,errInvalidChanNumber
  1789.     ERROR    ID_gusGetVolume
  1790.  
  1791. @@done:
  1792.     ret
  1793.  
  1794. ENDP
  1795.  
  1796.  
  1797.  
  1798.  
  1799. ;/***************************************************************************\
  1800. ;*
  1801. ;* Function:    int gusSetSample(int chan, int sample)
  1802. ;*
  1803. ;* Description: Sets up a sample for playing
  1804. ;*
  1805. ;* Input:    int chan        Channel number
  1806. ;*        int inst        Sample number from AddSample
  1807. ;*
  1808. ;* Returns:    MIDAS error code.
  1809. ;*
  1810. ;\***************************************************************************/
  1811.  
  1812. PROC    gusSetSample      _funct     chan : _int, inst : _int
  1813. USES    edi,_si,_bx
  1814.  
  1815.     mov    _bx,[chan]
  1816.     cmp    [chancount],_bx
  1817.     jle    @@errchn
  1818.     imul    _bx,_bx,size gusChannel     ; Channel block
  1819.  
  1820.     mov    _ax,[inst]
  1821.     test    _ax,_ax
  1822.     jz    @@errinst            ; No instrument at all?
  1823.     cmp    [numInsts],_ax
  1824.     jb    @@errinst
  1825.  
  1826.     mov    _dx,_ax
  1827.     dec    _dx                ; Table starts from 1
  1828.     imul    _dx,_dx,SIZE gusInstrument
  1829.     LOADPTR es,_si,[Instruments]
  1830.     add    _si,_dx
  1831.  
  1832.     cmp    [_bx+channels.inst],_ax
  1833.     je    @@nochange
  1834.  
  1835.     mov    [_bx+channels.inst],_ax     ; Set instrument
  1836.  
  1837.     cmp    [_essi+gusInstrument.length],0
  1838.     je    @@stop
  1839.  
  1840.     mov    _cx,[_essi+gusInstrument.sampleType]
  1841.     mov    [_bx+channels.sampleType],_cx
  1842.  
  1843.     mov    ecx,[_essi+gusInstrument.sample] ; Start address
  1844.     mov    [_bx+channels.scurrent],ecx
  1845.     mov    edi,ecx
  1846.  
  1847.     mov    _dx,[_essi+gusInstrument.loop1Type]
  1848.     mov    [_bx+channels.loop1Type],_dx    ; Copy loop 1 type
  1849.     mov    _dx,[_essi+gusInstrument.loop2Type]
  1850.     mov    [_bx+channels.loop2Type],_dx    ; Copy loop 2 type
  1851.  
  1852.     mov    _dx,[_essi+gusInstrument.loopMode]
  1853.     mov    [_bx+channels.loopMode],_dx    ; Copy loop mode
  1854.  
  1855.     cmp    _dx,sdLoopNone
  1856.     je    @@noloop
  1857.     cmp    _dx,sdLoopAmigaNone
  1858.     je    @@noloop
  1859.  
  1860. IFDEF    __16__
  1861.     xor    eax,eax
  1862. ENDIF
  1863.     push    ecx edi
  1864.     mov    _ax,[_essi+gusInstrument.loop2End]
  1865.     add    ecx,eax             ; Loop 2 end address
  1866.     mov    [_bx+channels.l2end],ecx
  1867.     mov    _ax,[_essi+gusInstrument.loop2Start]
  1868.     add    edi,eax             ; Loop 2 end address
  1869.     mov    [_bx+channels.l2start],edi
  1870.     pop    edi ecx
  1871.  
  1872.     mov    _ax,[_essi+gusInstrument.loop1End]
  1873.     add    edi,eax             ; Loop end address
  1874.     mov    _ax,[_essi+gusInstrument.loop1Start]
  1875.     add    ecx,eax             ; Loop start address
  1876.     jmp    @@duu
  1877.  
  1878. @@noloop:
  1879. IFDEF    __16__
  1880.     xor    eax,eax
  1881. ENDIF
  1882.     mov    _ax,[_essi+gusInstrument.length]
  1883.     add    edi,eax             ; Sample end address
  1884. @@duu:
  1885.     mov    [_bx+channels.sstart],ecx    ; Tell loop start to GUS
  1886.     mov    [_bx+channels.send],edi     ; And loop end
  1887.     or    [_bx+channels.status],gsSample
  1888.  
  1889. @@nochange:
  1890. IFNDEF NOSTEREO
  1891.     cmp    [mEnableSurround],0
  1892.     je    @@quit
  1893.  
  1894.     mov    _bx,[chan]
  1895.     add    _bx,[chancount]
  1896.     imul    _bx,_bx,size gusChannel     ; Channel block
  1897.  
  1898.     mov    _ax,[inst]
  1899.  
  1900.     cmp    [_bx+channels.inst],_ax
  1901.     je    @@nochange2
  1902.  
  1903.     mov    [_bx+channels.inst],_ax     ; Set instrument
  1904.  
  1905.     mov    ecx,[_essi+gusInstrument.surround] ; Start address
  1906.     test    ecx,ecx
  1907.     jnz    @@ok2
  1908.     mov    ecx,[_essi+gusInstrument.sample] ; Start address
  1909. @@ok2:
  1910.     mov    edi,ecx
  1911. IFDEF    __16__
  1912.     xor    eax,eax
  1913. ENDIF
  1914.     mov    _dx,[_essi+gusInstrument.loopMode]
  1915.     mov    [_bx+channels.loopMode],_dx    ; Copy loop mode
  1916.  
  1917.     cmp    _dx,sdLoopNone
  1918.     je    @@noloop2
  1919.     cmp    _dx,sdLoopAmigaNone
  1920.     je    @@noloop2
  1921.  
  1922.     mov    _ax,[_essi+gusInstrument.loop1End]
  1923.     add    edi,eax             ; Loop end address
  1924.     mov    _ax,[_essi+gusInstrument.loop1Start]
  1925.     add    ecx,eax             ; Loop start address
  1926.     jmp    @@duu2
  1927.  
  1928. @@noloop2:
  1929.     mov    _ax,[_essi+gusInstrument.length]
  1930.     add    edi,eax             ; Sample end address
  1931. @@duu2:
  1932.     mov    [_bx+channels.sstart],ecx    ; Tell loop start to GUS
  1933.     mov    [_bx+channels.send],edi     ; And loop end
  1934.     or    [_bx+channels.status],gsSample
  1935.  
  1936. @@nochange2:
  1937. ENDIF
  1938. @@quit:
  1939.     xor    _ax,_ax
  1940.     ret
  1941.  
  1942. @@stop: call    gusStopSound LANG, [chan]
  1943.     ret
  1944.  
  1945. @@errinst:
  1946.     mov    _ax,errInvalidSampleHandle
  1947.     jmp    @@err
  1948. @@errchn:
  1949.     mov    _ax,errInvalidChanNumber
  1950. @@err:    ERROR    ID_gusSetSample
  1951.     ret
  1952. ENDP
  1953.  
  1954.  
  1955.  
  1956.  
  1957. ;/***************************************************************************\
  1958. ;*
  1959. ;* Function:    int gusGetSample(int chan, ushort *sample)
  1960. ;*
  1961. ;* Description: Gets the last sample set for playing
  1962. ;*
  1963. ;* Input:    int chan        channel number
  1964. ;*        int *sample        pointer to sample number
  1965. ;*
  1966. ;* Returns:    MIDAS error code. Sample number is written to *sample.
  1967. ;*
  1968. ;\***************************************************************************/
  1969.  
  1970. PROC    gusGetSample    _funct       chan : _int, inst : _ptr
  1971. USES    _bx
  1972.  
  1973.     mov    _bx,[chan]
  1974.     cmp    [chancount],_bx
  1975.     jle    @@errchn
  1976.     imul    _bx,_bx,size gusChannel       ; Channel block
  1977.  
  1978.     mov    _ax,[_bx+channels.inst]
  1979.     LOADPTR es,_bx,[inst]
  1980.     mov    [_esbx],_ax
  1981.  
  1982.     xor    _ax,_ax
  1983.     jmp    @@done
  1984.  
  1985. @@errchn:
  1986.     mov    _ax,errInvalidChanNumber
  1987.     ERROR    ID_gusGetSample
  1988.  
  1989. @@done:
  1990.     ret
  1991. ENDP
  1992.  
  1993.  
  1994.  
  1995.  
  1996. ;/***************************************************************************\
  1997. ;*
  1998. ;* Function:    int gusSetPosition(int chan, ushort pos)
  1999. ;*
  2000. ;* Description: Sets the playing position for a channel
  2001. ;*
  2002. ;* Input:    int chan        Channel number
  2003. ;*        int pos         New playing position
  2004. ;*
  2005. ;* Returns:    MIDAS error code.
  2006. ;*
  2007. ;\***************************************************************************/
  2008. PROC    gusSetPosition _funct      chan : _int, pos : _int
  2009. USES    _si,_bx
  2010.  
  2011.     mov    _bx,[chan]
  2012.     cmp    [chancount],_bx
  2013.     jle    @@err
  2014.     imul    _bx,_bx,size gusChannel     ; Channel block
  2015.  
  2016.     mov    _dx,[_bx+channels.inst]
  2017.     test    _dx,_dx
  2018.     jz    @@quit                ; No instrument?
  2019.  
  2020.     dec    _dx                ; Table starts from 1
  2021.     imul    _dx,_dx,SIZE gusInstrument
  2022.     LOADPTR es,_si,[Instruments]
  2023.     add    _si,_dx
  2024.  
  2025. IFDEF    __16__
  2026.     xor    ecx,ecx
  2027. ENDIF
  2028.     mov    _cx,[pos]
  2029.     cmp    [_essi+gusInstrument.sampleType],smp16bit
  2030.     jne    @@skip
  2031.     add    _cx,_cx
  2032. @@skip: cmp    [_essi+gusInstrument.length],_cx ; Over from end?
  2033.     jae    @@ok
  2034.  
  2035.     cmp    [_essi+gusInstrument.loopMode],sdLoopAmiga
  2036.     je    @@ale
  2037.  
  2038.     call    gusStopSound LANG, [chan]
  2039.     ret
  2040.  
  2041. @@ale:    mov    _cx,[_essi+gusInstrument.loop1Start] ; Yep. Start from loop
  2042.  
  2043. @@ok:    add    ecx,[_essi+gusInstrument.sample] ; Add sample start to position
  2044.     mov    [_bx+channels.scurrent],ecx     ; Set start position
  2045.     and    [_bx+channels.status],NOT gsStop
  2046.     or    [_bx+channels.status],gsRetrig
  2047.     mov    [_bx+channels.onoff],1
  2048.  
  2049. IFNDEF NOSTEREO
  2050.     cmp    [mEnableSurround],0
  2051.     je    @@quit
  2052.  
  2053.     mov    _bx,[chan]
  2054.     add    _bx,[chancount]
  2055.     imul    _bx,_bx,size gusChannel       ; Channel block
  2056. IFDEF    __16__
  2057.     xor    ecx,ecx
  2058. ENDIF
  2059.     mov    _cx,[pos]
  2060.     cmp    [_essi+gusInstrument.surround],0
  2061.     je    @@nop
  2062.     add    ecx,[_essi+gusInstrument.surround] ; Add sample start to position
  2063.     jmp    @@kop
  2064. @@nop:    add    ecx,[_essi+gusInstrument.surround] ; Add sample start to position
  2065. @@kop:    mov    [_bx+channels.scurrent],ecx     ; Set start position
  2066.     and    [_bx+channels.status],NOT gsStop
  2067.     or    [_bx+channels.status],gsRetrig
  2068.     mov    [_bx+channels.onoff],1
  2069. ENDIF
  2070. @@quit: xor    _ax,_ax
  2071.     ret
  2072.  
  2073. @@err:    mov    _ax,errInvalidChanNumber
  2074.     ERROR    ID_gusSetPosition
  2075.     ret
  2076. ENDP
  2077.  
  2078.  
  2079. ;/***************************************************************************\
  2080. ;*
  2081. ;* Function:    int gusGetPosition(int chan, ushort *pos)
  2082. ;*
  2083. ;* Description: Gets the playing position of a channel
  2084. ;*
  2085. ;* Input:    int chan         Channel number
  2086. ;*
  2087. ;* Returns:    MIDAS error code.
  2088. ;*
  2089. ;\***************************************************************************/
  2090.  
  2091. PROC    gusGetPosition _funct      chan : _int, pos:_ptr
  2092. USES    _si,_bx
  2093.  
  2094.     mov    _bx,[chan]
  2095.     cmp    [chancount],_bx
  2096.     jle    @@err
  2097.  
  2098.     cli
  2099.     mov    _dx,[voicesel]            ; Select voice
  2100.     mov    _ax,_bx
  2101.     out    dx,al
  2102.  
  2103.     regsel    80h                ; Voice control
  2104.     add    _dx,2
  2105.     in    al,dx
  2106.     test    al,1
  2107.     jnz    @@stopped            ; Is sound on?
  2108.  
  2109.     imul    _bx,_bx,size gusChannel     ; Channel block
  2110.  
  2111.     ;FIXME!
  2112.     cmp    [_bx+channels.sampleType],smp16bit
  2113.     je    @@stopped
  2114.  
  2115. @@huuko:
  2116.     regsel    8ah                ; Current position high
  2117.     inc    _dx
  2118.     in    ax,dx
  2119. IFDEF    __16__
  2120.     xor    ecx,ecx
  2121. ENDIF
  2122.     mov    _cx,_ax
  2123.     and    _cx,01fffh
  2124.     shl    ecx,7
  2125.  
  2126.     regsel    8bh                ; Current position low
  2127.     inc    _dx
  2128.     in    ax,dx
  2129.     shr    ax,9
  2130.     or    _cx,_ax
  2131.  
  2132.     call    gusdelay
  2133.  
  2134. ; Read the value again to avoid GF1 self-modifying...
  2135.     regsel    8ah                ; Current position high
  2136.     inc    _dx
  2137.     in    ax,dx
  2138. IFDEF    __16__
  2139.     xor    esi,esi
  2140. ENDIF
  2141.     mov    _si,_ax
  2142.     and    _si,01fffh
  2143.     shl    esi,7
  2144.  
  2145.     regsel    8bh                ; Current position low
  2146.     inc    dx
  2147.     in    ax,dx
  2148.     shr    ax,9
  2149.     or    _si,_ax
  2150.  
  2151. ; Some sanity checking...
  2152.     sub    esi,ecx
  2153.     js    @@huuko
  2154.     cmp    esi,16
  2155.     ja    @@huuko
  2156.  
  2157.     mov    _bx,[_bx+channels.curinst]
  2158.     dec    _bx
  2159.     imul    _bx,_bx,SIZE gusInstrument
  2160.  
  2161.     LOADPTR es,_si,[Instruments]
  2162.     sub    ecx,[_essi+_bx+gusInstrument.sample]
  2163.     jns    @@oke2
  2164.  
  2165.     xor    ecx,ecx
  2166.     jmp    @@oke
  2167. @@oke2:
  2168.     cmp    ecx,[_essi+_bx+gusInstrument.length]
  2169.     jb    @@oke
  2170.  
  2171.     mov    ecx,[_essi+_bx+gusInstrument.length]
  2172.     dec    ecx
  2173.  
  2174. @@oke:    sti
  2175.     LOADPTR es,_bx,[pos]
  2176.     mov    [_esbx],_cx
  2177.     xor    _ax,_ax
  2178.     ret
  2179.  
  2180. @@stopped:                    ; No sound is being played
  2181.     xor    _cx,_cx
  2182.     jmp    @@oke
  2183.     ret
  2184.  
  2185. @@err:    mov    _ax,errInvalidChanNumber
  2186.     ERROR    ID_gusGetPosition
  2187.     ret
  2188.  
  2189. ENDP
  2190.  
  2191.  
  2192. ;/***************************************************************************\
  2193. ;*
  2194. ;* Function:    int gusGetDirection(int chan, ushort *dir)
  2195. ;*
  2196. ;* Description: Gets the playing direction of a channel
  2197. ;*
  2198. ;* Input:    int chan        Channel number
  2199. ;*        int dir         Pointer to direction
  2200. ;*
  2201. ;* Returns:    MIDAS error code.
  2202. ;*        Playing direction is stored in *dir.
  2203. ;*
  2204. ;\***************************************************************************/
  2205.  
  2206. PROC    gusGetDirection _funct       chan : _int, dir : _ptr
  2207. USES    _bx
  2208.  
  2209.     mov    _ax,[chan]
  2210.     cmp    [chancount],_ax
  2211.     jle    @@err
  2212.  
  2213.     cli
  2214.     mov    _dx,[voicesel]            ; Select voice
  2215.     out    dx,al
  2216.  
  2217.     regsel    80h                ; Voice control
  2218.     add    _dx,2
  2219.     in    al,dx
  2220.     sti
  2221.  
  2222.     test    al,40h
  2223.     jnz    @@back
  2224.     mov    _ax,1
  2225.     jmp    @@end
  2226. @@back:
  2227.     mov    _ax,-1
  2228. @@end:    LOADPTR es,_bx,[pos]
  2229.     mov    [_esbx],_ax
  2230.     xor    _ax,_ax
  2231.     ret
  2232.  
  2233. @@err:    mov    _ax,errInvalidChanNumber
  2234.     ERROR    ID_gusGetDirection
  2235.     ret
  2236. ENDP
  2237.  
  2238.  
  2239. ;/***************************************************************************\
  2240. ;*
  2241. ;* Function:    int gusSetPanning(int chan, int panning)
  2242. ;*
  2243. ;* Description: Sets the panning position for a channel
  2244. ;*
  2245. ;* Input:    int channel        Channel number
  2246. ;*        int panning        Panning value (See enum)
  2247. ;*
  2248. ;* Returns:    MIDAS error code.
  2249. ;*
  2250. ;\***************************************************************************/
  2251.  
  2252. PROC    gusSetPanning    _funct       chan : _int, panning : _int
  2253. USES    _bx
  2254.  
  2255.     mov    _ax,[chan]
  2256.     cmp    [chancount],_ax
  2257.     jle    @@err
  2258.     mov    _dx,[voicesel]            ; Voice Select
  2259.     out    dx,al
  2260.  
  2261.     mov    _bx,_ax
  2262.     imul    _bx,_bx,size gusChannel     ; Channel block
  2263.  
  2264.     mov    _ax,[panning]
  2265.     cmp    [_bx+channels.panning],_ax
  2266.     je    @@kwit
  2267.     mov    [_bx+channels.panning],_ax    ; Panning position
  2268.  
  2269. IFNDEF NOSTEREO
  2270.     cmp    [monoFlag],1
  2271.     je    @@kwit                ; Skip if forced mono
  2272.  
  2273.     cmp    _ax,panSurround
  2274.     jne    @@juuh
  2275.  
  2276.     cmp    [mEnableSurround],0
  2277.     jne    @@huu
  2278.     xor    _ax,_ax             ; No surround enabled --> middle
  2279.     jmp    @@juuh
  2280.  
  2281. @@huu:
  2282.     mov    [_bx+channels.panningHW],0    ; Extreme left
  2283.     or    [_bx+channels.status],gsPanning
  2284.  
  2285.     mov    [_bx+channels.surround],1    ; This is a surround channel
  2286.     mov    _ax,[_bx+channels.status]    ; Copy status (mute)
  2287.  
  2288.     mov    _cx,[chancount]
  2289.     imul    _cx,_cx,size gusChannel     ; Channel block
  2290.     add    _bx,_cx
  2291.  
  2292.     mov    [_bx+channels.panningHW],15    ; Extreme right
  2293.     mov    [_bx+channels.surround],1    ; This is a surround, too
  2294.     mov    [_bx+channels.status],_ax
  2295.     jmp    @@jatkuu
  2296.  
  2297. @@juuh: mov    [_bx+channels.surround],0    ; Normal channel
  2298.  
  2299.     sar    _ax,3
  2300.     or    _ax,_ax             ; Sign
  2301.     jns    @@pos
  2302.     inc    _ax
  2303. @@pos:    add    _ax,7
  2304.     mov    [_bx+channels.panningHW],_ax
  2305.     or    [_bx+channels.status],gsPanning
  2306.  
  2307.     mov    _bx,[chan]
  2308.     add    _bx,[chancount]
  2309.     cmp    _bx,32
  2310.     jae    @@jatkuu
  2311.     imul    _bx,_bx,size gusChannel     ; Channel block
  2312.     mov    [_bx+channels.surround],0    ; No longer surround channel (?)
  2313.     or    [_bx+channels.status],gsMute
  2314.  
  2315. @@jatkuu:
  2316.     mov    [masterchanged],1        ; Force reset of volume
  2317. ENDIF
  2318. @@kwit: sti
  2319. @@quit: xor    _ax,_ax
  2320.     ret
  2321.  
  2322. @@err:    mov    _ax,errInvalidChanNumber
  2323.     ERROR    ID_gusSetPanning
  2324.     ret
  2325. ENDP
  2326.  
  2327.  
  2328.  
  2329. ;/***************************************************************************\
  2330. ;*
  2331. ;* Function:    int gusGetPanning(int chan, short *panning)
  2332. ;*
  2333. ;* Description: Gets the panning position for a channel
  2334. ;*
  2335. ;* Input:    int channel        Channel number
  2336. ;*        int *panning        Pointer to panning value
  2337. ;*
  2338. ;* Returns:    MIDAS error code.
  2339. ;*        Panning value is stored in *panning.
  2340. ;*
  2341. ;\***************************************************************************/
  2342.  
  2343. PROC    gusGetPanning    _funct       channel : _int, panning : _ptr
  2344. USES    _bx
  2345.  
  2346.     mov    _bx,[channel]
  2347.     cmp    [chancount],_bx
  2348.     jle    @@err
  2349.     imul    _bx,_bx,size gusChannel     ; Channel block
  2350.     mov    _ax,[_bx+channels.panning]    ; Panning position
  2351.     LOADPTR es,_bx,[panning]
  2352.     mov    [_esbx],_ax
  2353.     xor    _ax,_ax
  2354.     ret
  2355.  
  2356. @@err:    mov    _ax,errInvalidChanNumber
  2357.     ERROR    ID_gusGetPanning
  2358.     ret
  2359. ENDP
  2360.  
  2361.  
  2362.  
  2363. ;/***************************************************************************\
  2364. ;*
  2365. ;* Function:    int gusMuteChannel(int chan, int mute)
  2366. ;*
  2367. ;* Description: Mutes or unmutes a channel
  2368. ;*
  2369. ;* Input:    int chan        Channel number
  2370. ;*        int mute        Unmute = 0 / Mute = 1
  2371. ;*
  2372. ;* Returns:    MIDAS error code.
  2373. ;*
  2374. ;\***************************************************************************/
  2375.  
  2376. PROC    gusMuteChannel    _funct       chan : _int, mute : _int
  2377. USES    _bx
  2378.  
  2379.     mov    _bx,[chan]
  2380.     cmp    [chancount],_bx
  2381.     jle    @@err
  2382.     imul    _bx,_bx,SIZE gusChannel
  2383.  
  2384.     cmp    [mute],1
  2385.     je    @@mute
  2386.     and    [_bx+channels.status],NOT gsMute
  2387.     or    [_bx+channels.status],gsVolume
  2388.     jmp    @@guu
  2389. @@mute:
  2390.     or     [_bx+channels.status],gsMute OR gsVolume
  2391.  
  2392. @@guu:
  2393. IFNDEF NOSTEREO
  2394.     cmp    [_bx+channels.surround],0
  2395.     je    @@pois
  2396.  
  2397.     mov    _bx,[chan]
  2398.     add    _bx,[chancount]
  2399.     imul    _bx,_bx,SIZE gusChannel
  2400.  
  2401.     cmp    [mute],1
  2402.     je    @@mute2
  2403.     and    [_bx+channels.status],NOT gsMute
  2404.     or    [_bx+channels.status],gsVolume
  2405.     jmp    @@pois
  2406. @@mute2:
  2407.     or     [_bx+channels.status],gsMute OR gsVolume
  2408. ENDIF
  2409. @@pois: xor    _ax,_ax
  2410.     ret
  2411.  
  2412. @@err:    mov    _ax,errInvalidChanNumber
  2413.     ERROR    ID_gusMuteChannel
  2414.     ret
  2415.  
  2416. ENDP
  2417.  
  2418.  
  2419. ;/***************************************************************************\
  2420. ;*
  2421. ;* Function:    int gusAddSample(sdSample *sample, int copySample,
  2422. ;*                 int *sdNum);
  2423. ;*
  2424. ;* Description:  Adds a new sample to the sample list
  2425. ;*
  2426. ;* Input:     sdSample *sample    pointer to sample information
  2427. ;*                    structure.
  2428. ;*         int copySample     1 if sample should be copied
  2429. ;*         int *sdNum        pointer to variable to store the SD
  2430. ;*                    sample handle
  2431. ;*
  2432. ;* Returns:    MIDAS error code.
  2433. ;*        SD sample handle is stored in *sdNum.
  2434. ;*
  2435. ;\***************************************************************************/
  2436.  
  2437. PROC    gusAddSample _funct    sample : _ptr, copysample : _int, sdNum : _ptr
  2438. USES    _si,_di,_bx
  2439. LOCAL    gusmem : dword, gusmem2 : dword, smpStart : _ptr, glength : _int, \
  2440.     loopMode : _int, loopStart : _int
  2441.  
  2442.     LOADPTR gs,_si,[sample]
  2443.     cmp    [_gssi+sdSample.sampleType],smp8bit
  2444.     je    @@instok
  2445.     cmp    [_gssi+sdSample.sampleType],smp16bit
  2446.     je    @@instok
  2447.     cmp    [_gssi+sdSample.sampleType],smpNone
  2448.     jne    @@errinst
  2449.     mov    [_gssi+sdSample.sampleLength],0
  2450. @@instok:
  2451.     mov    _ax,[instpos]
  2452.     dec    _ax                ; Table starts from 1
  2453.     imul    _ax,_ax,SIZE gusInstrument
  2454.     LOADPTR es,_di,[Instruments]
  2455.     add    _di,_ax
  2456.  
  2457.     cmp    [_gssi+sdSample.sampleLength],0
  2458.     je    @@nsurr
  2459.  
  2460.     cmp    [_gssi+sdSample.sampleType],smp8bit
  2461.     jne    @@not8bit
  2462.  
  2463.     ; FIXME!!!!
  2464.     mov    _cx,[_gssi+sdSample.sampleLength]
  2465.  
  2466.     PUSHSEGREG es
  2467.     LOADPTR es,_bx,[_gssi+sdSample.sample]    ; Pointer to sample
  2468. @@signloop:
  2469.     xor    [byte _esbx],80h
  2470.     inc    _bx
  2471.     dec    _cx
  2472.     jnz    @@signloop
  2473.     POPSEGREG es
  2474.  
  2475. @@not8bit:
  2476.     PUSHSEGREG es gs
  2477.     call    gusMalloc LANG, [_gssi+sdSample.sampleLength],    \
  2478.          [_gssi+sdSample.sampleType], ptr_to temp
  2479.     POPSEGREG gs es
  2480.     test    _ax,_ax
  2481.     jnz    @@err
  2482.  
  2483.     mov    eax,[temp]
  2484.     mov    [gusmem],eax
  2485.  
  2486.     mov    [_esdi+gusInstrument.sample],eax   ; Sample start
  2487.     mov    [_esdi+gusInstrument.surround],0
  2488.  
  2489. IFNDEF NOSTEREO
  2490.     cmp    [mEnableSurround],0
  2491.     je    @@nsurr
  2492.     cmp    [_gssi+sdSample.sampleType],smp16bit
  2493.     je    @@nsurr
  2494.  
  2495.     PUSHSEGREG es
  2496.     call    gusMalloc LANG, [_gssi+sdSample.sampleLength],    \
  2497.          [_gssi+sdSample.sampleType], ptr_to temp
  2498.     POPSEGREG es
  2499.     test    _ax,_ax
  2500.     jnz    @@err
  2501.  
  2502.     mov    eax,[temp]
  2503.     mov    [gusmem2],eax
  2504.     mov    [_esdi+gusInstrument.surround],eax ; Surround sample start
  2505. ENDIF
  2506. @@nsurr:
  2507.     COPYPTR [smpStart],[_gssi+sdSample.sample]
  2508.  
  2509.     ; FIXME!
  2510.     mov    _ax,[_gssi+sdSample.sampleType]
  2511.     cmp    _ax,smpNone
  2512.     jne    @@smp2
  2513.     mov    _ax,smp8bit
  2514. @@smp2:
  2515.     mov    [_esdi+gusInstrument.sampleType],_ax
  2516.  
  2517.     mov    _ax,[_gssi+sdSample.sampleLength]
  2518.     mov    [_esdi+gusInstrument.length],_ax ; Sample length
  2519.  
  2520.     mov    _ax,[_gssi+sdSample.loopMode]
  2521.     mov    [_esdi+gusInstrument.loopMode],_ax
  2522.     mov    [loopMode],_ax
  2523.  
  2524.     mov    _ax,[_gssi+sdSample.loop1Type]
  2525.     mov    [_esdi+gusInstrument.loop1Type],_ax
  2526.  
  2527.     mov    _ax,[_gssi+sdSample.loop1Start]
  2528.     mov    [_esdi+gusInstrument.loop1Start],_ax
  2529.  
  2530.     mov    _ax,[_gssi+sdSample.loop1End]
  2531.     mov    [_esdi+gusInstrument.loop1End],_ax
  2532.  
  2533.     mov    _ax,[_gssi+sdSample.loop2Type]
  2534.     mov    [_esdi+gusInstrument.loop2Type],_ax
  2535.  
  2536.     mov    _ax,[_gssi+sdSample.loop2Start]
  2537.     mov    [_esdi+gusInstrument.loop2Start],_ax
  2538.  
  2539.     mov    _ax,[_gssi+sdSample.loop2End]
  2540.     mov    [_esdi+gusInstrument.loop2End],_ax
  2541.  
  2542. ;PK-
  2543.     cmp    [loopMode],sdLoop2
  2544.     jne    @@loop1
  2545. ;-PK
  2546.     cmp    [_gssi+sdSample.loop2Type],loopNone
  2547.     je    @@loop1
  2548.     mov    _ax,[_gssi+sdSample.loop2Start]
  2549.     jmp    @@loopok
  2550. @@loop1:
  2551.     mov    _ax,[_gssi+sdSample.loop1Start]
  2552. @@loopok:
  2553.     mov    [loopStart],_ax
  2554.  
  2555.     mov    _cx,[_gssi+sdSample.sampleLength]
  2556.     test    _cx,_cx
  2557.     jz    @@qwit
  2558.  
  2559.     LOADPTR es,_si,[smpStart]        ; Pointer to sample
  2560.  
  2561.     mov    ebx,[gusmem]            ; Start in GUS memory
  2562. IFDEF    __32__
  2563.     xor    edi,edi
  2564. ENDIF
  2565.     mov    di,bx
  2566.     shr    ebx,16
  2567.  
  2568.     mov    [flag],1
  2569.  
  2570. @@dumploop2:
  2571.     cli
  2572.     regsel    44h                ; Addr hi
  2573.     add    _dx,2                ; 3x5
  2574.     mov    _ax,_bx
  2575.     out    dx,al                ; upper bits of address
  2576.     sti
  2577.  
  2578.     regsel    43h                ; Addr lo
  2579. @@dumploop:
  2580.     mov    _dx,[selreg]
  2581.     mov    _ax,_di
  2582.     inc    _dx                ; 3x4
  2583.     out    dx,ax
  2584.     add    _dx,3                ; 3x7
  2585.     mov    al,[_essi]            ; Get data
  2586.     inc    _si
  2587.     out    dx,al
  2588.  
  2589.     inc    di
  2590.     jz    @@yli64
  2591.     dec    _cx
  2592.     jnz    @@dumploop            ; Dump the whole sample
  2593.     jmp    @@quit
  2594.  
  2595. @@yli64:
  2596.     inc    _bx                ; Crossed 64kb border
  2597.     dec    _cx
  2598.     jnz    @@dumploop2            ; Dump the whole sample
  2599.  
  2600.  
  2601. @@quit:
  2602.     cmp    [loopMode],sdLoopNone
  2603.     je    @@noloob
  2604.     cmp    [loopMode],sdLoop1Rel
  2605.     je    @@noloob
  2606.     cmp    [loopMode],sdLoopAmigaNone
  2607.     je    @@noloob
  2608. @@loobed:                    ; Copy loop to next 32 byte border
  2609.     LOADPTR es,_si,[smpStart]
  2610.     add    _si,[loopStart]
  2611.  
  2612.     mov    _dx,_di
  2613.     mov    _cx,64
  2614.     and    _dx,01fh             ; AND lowest bits off
  2615.     sub    _cx,_dx
  2616.  
  2617. @@dumploop3:
  2618.     cli
  2619.     regsel    44h                ; Addr hi
  2620.     add    _dx,2                ; 3x5
  2621.     mov    _ax,_bx
  2622.     out    dx,al                ; upper bits of address
  2623.     sti
  2624.  
  2625.     regsel    43h                ; Addr lo
  2626. @@dumploop4:
  2627.     mov    _dx,[selreg]
  2628.     mov    _ax,_di
  2629.     inc    _dx                ; 3x4
  2630.  
  2631.     out    dx,ax
  2632.     add    _dx,3                ; 3x7
  2633.     mov    al,[_essi]            ; Get data
  2634.     inc    _si
  2635.     out    dx,al
  2636.  
  2637.     inc    di
  2638.     jz    @@yli642
  2639.     dec    _cx
  2640.     jnz    @@dumploop4            ; Do whole loop
  2641.     jmp    @@qwti
  2642.  
  2643. @@yli642:
  2644.     inc    _bx                ; Crossed 64kb border
  2645.     dec    _cx
  2646.     jnz    @@dumploop3            ; Do whole loop
  2647.     jmp    @@qwti
  2648.  
  2649.  
  2650. @@noloob:                    ; Copy the last byte
  2651.     dec    _si
  2652.     mov    _dx,_di
  2653.     mov    _cx,64
  2654.     and    _dx,01fh            ; AND lowest bits away...
  2655.     sub    _cx,_dx
  2656.  
  2657. @@dumploop5:
  2658.     cli
  2659.     regsel    44h                ; addr hi
  2660.     add    _dx,2                ; 3x5
  2661.     mov    _ax,_bx
  2662.     out    dx,al                ; upper bits of address
  2663.     sti
  2664.  
  2665.     regsel    43h                ; addr lo
  2666. @@dumploop6:
  2667.     mov    _dx,[selreg]
  2668.     inc    _dx                ; 3x4
  2669.     mov    _ax,_di
  2670.  
  2671.     out    dx,ax
  2672.     mov    al,[_essi]            ; Get data
  2673.     add    _dx,3                ; 3x7
  2674.     out    dx,al
  2675.  
  2676.     inc    di
  2677.     jz    @@yli643
  2678.     dec    _cx
  2679.     jnz    @@dumploop6
  2680.     jmp    @@qwti
  2681.  
  2682. @@yli643:
  2683.     inc    _bx                ; Crossed 64kb border
  2684.     dec    _cx
  2685.     jnz    @@dumploop5
  2686.  
  2687. @@qwti:
  2688.     LOADPTR gs,_si,[sample]
  2689.  
  2690. IFNDEF NOSTEREO
  2691.     cmp    [mEnableSurround],0
  2692.     je    @@qwit
  2693.     cmp    [_gssi+sdSample.sampleType],smp16bit
  2694.     je    @@qwit
  2695.  
  2696.     call    CopySurroundSample LANG, [smpStart], [glength], [loopStart],\
  2697.                      [loopMode], [gusmem2]
  2698.  
  2699. ENDIF
  2700. @@qwit:
  2701.     cmp    [_gssi+sdSample.sampleType],smp8bit
  2702.     jne    @@not8bit2
  2703.  
  2704.     ; FIXME!!!!
  2705.     mov    _cx,[_gssi+sdSample.sampleLength]
  2706.     test    _cx,_cx
  2707.     jz    @@not8bit2
  2708.  
  2709.     PUSHSEGREG es
  2710.     LOADPTR es,_bx,[_gssi+sdSample.sample]    ; Pointer to sample
  2711. @@signloop2:
  2712.     xor    [byte _esbx],80h
  2713.     inc    _bx
  2714.     dec    _cx
  2715.     jnz    @@signloop2
  2716.     POPSEGREG es
  2717.  
  2718. @@not8bit2:
  2719.     push    [instpos]            ; Return instrument number
  2720.  
  2721.     mov    [flag],0
  2722.  
  2723.     mov    _ax,[instpos]
  2724.     mov    _bx,_ax
  2725.     dec    _bx
  2726.     imul    _bx,_bx,SIZE gusInstrument
  2727.     LOADPTR es,_si,[Instruments]
  2728.     add    _si,_bx
  2729. @@search:                    ; Search next free instrument
  2730.     cmp    [_essi+gusInstrument.sampleType],smpNone
  2731.     je    @@found
  2732.     add    _si,SIZE gusInstrument
  2733.     inc    _ax
  2734.     jmp    @@search
  2735.  
  2736. @@found:
  2737.     mov    [instpos],_ax
  2738.     pop    _ax
  2739.     LOADPTR es,_bx,[sdNum]
  2740.     mov    [_esbx],_ax
  2741.  
  2742.     cmp    [numInsts],_ax
  2743.     jae    @@huu
  2744.     mov    [numInsts],_ax
  2745. @@huu:
  2746.     xor    _ax,_ax
  2747.     ret
  2748.  
  2749.  
  2750. @@errinst:
  2751.     mov    _ax,errInvalidInst
  2752. @@err:    ERROR    ID_gusAddSample
  2753.     ret
  2754. ENDP
  2755.  
  2756.  
  2757. IFNDEF NOSTEREO
  2758. PROC    CopySurroundSample NEAR inst : _ptr, glength : _int, loopStart : _int,\
  2759.                 gloop : _int, gusmem : dword
  2760. USES    _si,_di,_bx
  2761.  
  2762.     LOADPTR es,_si,[inst]            ; Pointer to sample
  2763.  
  2764.     mov    _cx,[glength]
  2765.  
  2766.     mov    ebx,[gusmem]            ; Start in GUS memory
  2767.     mov    _di,_bx
  2768.     shr    ebx,16
  2769.  
  2770. @@dumploop2:
  2771.     cli
  2772.     regsel    44h
  2773.     add    _dx,2                ;3x5
  2774.     mov    _ax,_bx
  2775.     out    dx,al                ;upper bits of address
  2776.     sti
  2777.  
  2778.     regsel    43h
  2779. @@dumploop:
  2780.     mov    _dx,[selreg]
  2781.     inc    _dx                ; 3x4
  2782.     mov    _ax,_di
  2783.     out    dx,ax
  2784.     add    _dx,3                ; 3x7
  2785.     mov    al,[_essi]            ; Get data
  2786.     inc    _si
  2787.     not    al                ; 180 degree phase transformation
  2788.     out    dx,al
  2789.  
  2790.     inc    di
  2791.     jz    @@yli64
  2792.     dec    _cx
  2793.     jnz    @@dumploop            ; Dump the whole sample
  2794.     jmp    @@quit
  2795.  
  2796. @@yli64:
  2797.     inc    _bx                ; Crossed 64kb border
  2798.     dec    _cx
  2799.     jnz    @@dumploop2            ; Dump the whole sample
  2800.  
  2801. @@quit:
  2802.     cmp    [loopMode],sdLoopNone
  2803.     je    @@noloob
  2804.     cmp    [loopMode],sdLoop1Rel
  2805.     je    @@noloob
  2806.     cmp    [loopMode],sdLoopAmigaNone
  2807.     je    @@noloob
  2808.  
  2809. @@loobed:                    ; Copy loop to next 32 byte border
  2810.     LOADPTR es,_si,[inst]
  2811.     add    _si,[loopStart]
  2812.  
  2813.     mov    _dx,_di
  2814.     and    _dx,01fh            ; AND the lowest bits away...
  2815.     mov    _cx,64
  2816.     sub    _cx,_dx
  2817.  
  2818. @@dumploop3:
  2819.     cli
  2820.     regsel    44h
  2821.     add    _dx,2                ;3x5
  2822.     mov    _ax,_bx
  2823.     out    dx,al                ;upper bits of address
  2824.     sti
  2825.  
  2826.     regsel    43h
  2827. @@dumploop4:
  2828.     mov    _dx,[selreg]
  2829.     mov    _ax,_di
  2830.     inc    _dx                ; 3x4
  2831.  
  2832.     out    dx,ax
  2833.     add    _dx,3                ; 3x7
  2834.     mov    al,[_essi]            ; Get data
  2835.     inc    _si
  2836.     not    al                ; 180 degree phase transformation
  2837.     out    dx,al
  2838.  
  2839.     inc    di
  2840.     jz    @@yli642
  2841.     dec    _cx
  2842.     jnz    @@dumploop4            ; Do whole loop
  2843.     jmp    @@qwit
  2844.  
  2845. @@yli642:
  2846.     inc    _bx                ; Crossed 64kb border
  2847.     dec    _cx
  2848.     jnz    @@dumploop3            ; Do whole loop
  2849.     jmp    @@qwit
  2850.  
  2851. @@noloob:                    ; Copy the last byte
  2852.     mov    _dx,_di
  2853.     dec    _si
  2854.     and    _dx,01fh            ; Alimmat pois
  2855.     mov    _cx,64
  2856.     sub    _cx,_dx
  2857.  
  2858. @@dumploop5:
  2859.     cli
  2860.     regsel    44h
  2861.     add    _dx,2                ;3x5
  2862.     mov    _ax,_bx
  2863.     out    dx,al                ;upper bits of address
  2864.     sti
  2865.  
  2866.     regsel    43h
  2867. @@dumploop6:
  2868.     mov    _dx,[selreg]
  2869.     mov    _ax,_di
  2870.     inc    _dx                ; 3x4
  2871.  
  2872.     out    dx,ax
  2873.     add    dx,3                ; 3x7
  2874.     mov    al,[_essi]            ; Get data
  2875.     not    al                ; 180 degree phase transformation
  2876.     out    dx,al
  2877.  
  2878.     inc    di
  2879.     jz    @@yli643
  2880.     dec    _cx
  2881.     jnz    @@dumploop6
  2882.     jmp    @@qwit
  2883. @@yli643:
  2884.     inc    _bx                ; Crossed 64kb border
  2885.     dec    _cx
  2886.     jnz    @@dumploop5
  2887. @@qwit:
  2888.     ret
  2889. ENDP
  2890. ENDIF
  2891.  
  2892. ;/***************************************************************************\
  2893. ;*
  2894. ;* Function:    int gusRemoveSample(int sample)
  2895. ;*
  2896. ;* Description: Removes a sample from the GUS SD internal tables
  2897. ;*        and frees it from GUS memory
  2898. ;*
  2899. ;* Input:    int sample        Sample number from AddSample
  2900. ;*
  2901. ;* Returns:    MIDAS error code.
  2902. ;*
  2903. ;\***************************************************************************/
  2904.  
  2905. PROC    gusRemoveSample _funct       sample : _int
  2906. USES    _si,_bx
  2907.  
  2908.     mov    _bx,[inst]
  2909.     dec    _bx
  2910.     imul    _bx,_bx,SIZE gusInstrument
  2911.     LOADPTR es,_si,[Instruments]
  2912.     add    _si,_bx
  2913.  
  2914.     cmp    [_essi+gusInstrument.sampleType],smpNone
  2915.     je    @@nothing
  2916.  
  2917.     mov    [_essi+gusInstrument.sampleType],smpNone ; Free instrument
  2918.  
  2919.     cmp    [_essi+gusInstrument.length],0
  2920.     je    @@nsurround
  2921.  
  2922.     PUSHSEGREG es
  2923.     call    gusFree LANG, [_essi+gusInstrument.sample]
  2924.     POPSEGREG es
  2925.     test    _ax,_ax
  2926.     jnz    @@err
  2927.  
  2928. IFNDEF NOSTEREO
  2929.     cmp    [_essi+gusInstrument.surround],0
  2930.     je    @@nsurround
  2931.  
  2932.     call    gusFree LANG, [_essi+gusInstrument.surround]
  2933.     test    _ax,_ax
  2934.     jnz    @@err
  2935. ENDIF
  2936. @@nsurround:
  2937.     mov    _ax,[inst]
  2938.     cmp    [instpos],_ax
  2939.     jbe    @@nothing
  2940.  
  2941.     mov    [instpos],_ax            ; Lowest instrument number
  2942. @@nothing:
  2943.     cmp    [numInsts],_ax
  2944.     jne    @@juu
  2945.  
  2946.     LOADPTR es,_si,[Instruments]
  2947.     mov    _cx,_ax
  2948.     mov    _bx,1
  2949.     mov    _ax,_bx
  2950. @@search:                    ; Search next free instrument
  2951.     cmp    [_essi+gusInstrument.sampleType],smpNone
  2952.     je    @@nop
  2953.     mov    _ax,_bx
  2954. @@nop:    add    _si,SIZE gusInstrument
  2955.     inc    _bx
  2956.     dec    _cx
  2957.     jnz    @@search
  2958.     mov    [numInsts],_ax
  2959. @@juu:    xor    _ax,_ax
  2960.     ret
  2961.  
  2962. @@err:    ERROR    ID_gusRemoveSample
  2963.     ret
  2964. ENDP
  2965.  
  2966.  
  2967.  
  2968. ;/***************************************************************************\
  2969. ;*
  2970. ;* Function:    int gusSetUpdRate(int rate)
  2971. ;*
  2972. ;* Description: Sets the update rate of SD.
  2973. ;*
  2974. ;* Input:    int rate        Rate in Hz*100
  2975. ;*
  2976. ;* Returns:    MIDAS error code.
  2977. ;*
  2978. ;\***************************************************************************/
  2979.  
  2980. PROC    gusSetUpdRate _funct     rate : _int
  2981.  
  2982.     mov    _ax,[rate]
  2983.     mov    [updRate],_ax
  2984.     xor    _ax,_ax
  2985.     ret
  2986. ENDP
  2987.  
  2988.  
  2989.  
  2990.  
  2991. ;/***************************************************************************\
  2992. ;*
  2993. ;* Function:     int gusStartPlay(void);
  2994. ;*
  2995. ;* Description:  Called before gusPlay() is called. This function doesn't
  2996. ;*         have to do anything, however.
  2997. ;*
  2998. ;* Returns:     MIDAS error code
  2999. ;*
  3000. ;\***************************************************************************/
  3001.  
  3002. PROC    gusStartPlay    _funct
  3003.  
  3004.     xor    _ax,_ax
  3005.     ret
  3006. ENDP
  3007.  
  3008.  
  3009.  
  3010.  
  3011. ;/***************************************************************************\
  3012. ;*
  3013. ;* Function:    int gusPlay(int *callMP)
  3014. ;*
  3015. ;* Description: Updates the GUS registers according to the Sound Device
  3016. ;*        internal datas
  3017. ;*
  3018. ;* Returns:    MIDAS error code.
  3019. ;*
  3020. ;\***************************************************************************/
  3021. PROC    gusPlay _funct       callMP : _ptr
  3022. LOCAL    chanc : _int, selsave : _int, voicesave : _int, retrigfl : _int
  3023. USES    _di,_si,_bx
  3024.  
  3025.     cmp    [paused],0
  3026.     jne    @@paused
  3027.  
  3028.     cmp    [chansOpen],0
  3029.     je    @@paused
  3030.  
  3031.     xor    _ax,_ax
  3032.     mov    _dx,[voicesel]
  3033.     in    al,dx
  3034.     mov    [voicesave],_ax
  3035.  
  3036.     mov    _dx,[selreg]
  3037.     in    al,dx
  3038.     cmp    [flag],0            ; Are we uploading
  3039.     je    @@kd                ; at the same time?
  3040.     mov    al,43h
  3041. @@kd:    mov    [selsave],_ax
  3042.  
  3043.     mov    [chanc],0            ; Start from channel 0
  3044.     xor    _si,_si             ; Channel data
  3045. @@loop:
  3046.     cmp    [_si+channels.onoff],0
  3047.     je    @@retrigged
  3048.  
  3049.     mov    _dx,[voicesel]            ; Select voice
  3050.     mov    _ax,[chanc]
  3051.     out    dx,al
  3052.  
  3053.     test    [_si+channels.status],gsStop OR gsRetrig ; Retrig / stop sound?
  3054.     jz    @@nothing
  3055.  
  3056.     and    [_si+channels.status],NOT gsStop
  3057.  
  3058. IF FASTGUS
  3059.     test    [_si+channels.status],gsRetrig
  3060.     jz    @@juststop
  3061.  
  3062.     regsel    9                ; Current volume
  3063.     inc    _dx
  3064.     mov    _ax,1500h
  3065.     out    dx,ax
  3066.  
  3067.     call    gusdelay
  3068.  
  3069.     out    dx,ax
  3070.     jmp    @@setfc
  3071.  
  3072. @@juststop:
  3073. ENDIF
  3074.     regsel    7                ; Volume ramp start
  3075.     add    _dx,2
  3076.     mov    al,15h                ; to zero
  3077.     out    dx,al
  3078.  
  3079.     regsel    0dh                ; Volume ramp control
  3080.     add    _dx,2
  3081.     mov    al,40h                ; Start decreasing ramp
  3082.     out    dx,al
  3083.  
  3084.     regsel    0                ; Voice control
  3085.     add    _dx,2
  3086.     mov    al,3                ; Stop voice
  3087.     out    dx,al
  3088.  
  3089.     call    gusdelay
  3090.  
  3091.     out    dx,al                ; again...
  3092.  
  3093.     regsel    0dh                ; Volume ramp control
  3094.     add    _dx,2
  3095.     mov    al,40h                ; Start decreasing ramp
  3096.     out    dx,al
  3097.     jmp    @@setfc
  3098.  
  3099. @@nothing:
  3100.     cmp    [masterchanged],0
  3101.     jnz    @@set
  3102.     test    [_si+channels.status],gsVolume
  3103.     jz    @@setfc
  3104. @@set:    and    [_si+channels.status],NOT gsVolume
  3105.     regsel    89h
  3106.     inc    _dx
  3107.     in    ax,dx
  3108.  
  3109.     mov    cx,ax
  3110.     xor    cl,cl
  3111.  
  3112.     mov    _ax,[_si+channels.volume]    ; To set volume
  3113.     test    [_si+channels.status],gsMute
  3114.     jz    @@oek2
  3115.     xor    _ax,_ax
  3116. @@oek2: mov    _bx,[mastervol]
  3117.     mul    bl
  3118.     shr    _ax,6
  3119.     mov    _bx,_ax
  3120.     add    _bx,_bx
  3121.     mov    bx,[voltable+_bx]
  3122.  
  3123.     cmp    [_si+channels.surround],0
  3124.     je    @@hu2
  3125.     sub    bh,10h                ; Halve the volume
  3126. @@hu2:    xor    bl,bl
  3127.     cmp    cx,bx
  3128.     je    @@setfc             ; Already at that value
  3129.     cmp    cx,bx
  3130.     jb    @@yli
  3131.     xchg    cx,bx
  3132.     mov    cl,40h
  3133. @@yli:
  3134.     regsel    0dh                ; Ramp Control
  3135.     add    _dx,2
  3136.     mov    al,3
  3137.     out    dx,al                ; Stop Ramp
  3138.  
  3139.     call    gusdelay
  3140.  
  3141.     out    dx,al                ; Stop Ramp
  3142.  
  3143.     regsel    7                ; Ramp start
  3144.     add    _dx,2
  3145.     mov    al,ch                ; From lower
  3146.     out    dx,al
  3147.  
  3148.     regsel    8                ; Ramp end
  3149.     add    _dx,2
  3150.     mov    al,bh                ; To higher volume
  3151.     out    dx,al
  3152.  
  3153.     regsel    0dh                ; Ramp Control
  3154.     add    _dx,2
  3155.     mov    al,cl
  3156.     out    dx,al                ; GO!
  3157.  
  3158.     call    gusdelay
  3159.  
  3160.     out    dx,al                ; GO!
  3161.  
  3162. @@setfc:
  3163.     test    [_si+channels.status],gsFC
  3164.     jz    @@setpan
  3165.  
  3166.     and    [_si+channels.status],NOT gsFC
  3167.     regsel    1                ; Frequency control
  3168.     inc    _dx
  3169. @@writefc:
  3170.     mov    _ax,[_si+channels.fc]
  3171.     out    dx,ax
  3172.  
  3173. ; Let's see if this helps the Tone Portamento problems... (PK)
  3174. ; Unfortunately this has no chances of working, reading GUS
  3175. ; registers is made from register+80h... (JP)
  3176.     if    0
  3177.     call    gusdelay
  3178.     in    ax,dx
  3179.     cmp    _ax,[_si+channels.fc]
  3180.     je    @@fcok
  3181.     call    gusdelay
  3182.     jmp    @@writefc
  3183. @@fcok:
  3184. ; End of TP fix
  3185.     endif
  3186.  
  3187.  
  3188. @@setpan:
  3189.     test    [_si+channels.status],gsPanning
  3190.     jz    @@stopped
  3191.  
  3192.     and    [_si+channels.status],NOT gsPanning
  3193.  
  3194.     cmp    [GUS.cardType], gusIW
  3195.     jz    @@iwsmoothpan        ; no crappy on/off panning for iw ;)
  3196. ; regular gus compatible panning
  3197.     regsel    12                ; Pan Position
  3198.     add    _dx,2
  3199.     mov    _ax,[_si+channels.panningHW]
  3200.     out    dx,al
  3201.     jmp    @@stopped
  3202. @@iwsmoothpan:
  3203.     mov    _bx, [_si+channels.panning]
  3204.     add    _bx, _bx
  3205. ;interwave synth right offset ( bigger blocks sound )
  3206.     regsel    0ch
  3207.     inc    dl
  3208.     mov    ax, [pantablemid+_bx]
  3209.     out    dx, ax
  3210.     regsel    1bh            ; right offset fine
  3211.     inc    dl
  3212.     mov    ax, [pantablemid+_bx]
  3213.     out    dx, ax
  3214.  
  3215.     neg    _bx
  3216. ;interwave synth left offset
  3217.     regsel    13h            ; left offset
  3218.     inc    dl
  3219.     mov    ax, [pantablemid+_bx]
  3220.     out    dx, ax
  3221.     regsel    1ch            ; left offset fine
  3222.     inc    dl
  3223.     mov    ax, [pantablemid+_bx]
  3224.     out    dx, ax
  3225.  
  3226. @@stopped:
  3227.     test    [_si+channels.status],gsSample
  3228.     jz    @@retrigged            ; No sample changed
  3229.  
  3230.     cmp    [_si+channels.loopMode],sdLoopAmigaNone
  3231.     je    @@ALE
  3232.     cmp    [_si+channels.loopMode],sdLoopAmiga
  3233.     jne    @@noALE
  3234.  
  3235. @@ALE:    test    [_si+channels.status],gsRetrig
  3236.     jnz    @@retrigged            ; Already to be retrigged
  3237.  
  3238. ; GUS-AMIGA-LOOP-EMULATOR (GALE) (TM) V1.14!!!
  3239.  
  3240.     regsel    80h                ; Voice control
  3241.     add    _dx,2
  3242.     in    al,dx
  3243.  
  3244.     test    al,1
  3245.     jz    @@soundon
  3246.  
  3247.     cmp    [_si+channels.loopMode],sdLoopAmigaNone ; Next sample looped?
  3248.     je    @@stopsound            ; No
  3249.  
  3250.     mov    _ax,[_si+channels.inst]
  3251.     mov    [_si+channels.curinst],_ax
  3252.  
  3253.     mov    ebx,[_si+channels.sstart]
  3254.     jmp    @@startfromloop         ; Start from loop start
  3255.  
  3256. @@soundon:
  3257.     mov    eax,[_si+channels.frequency]
  3258.     imul    eax,eax,100            ; updRate is Hz*100
  3259.     xor    edx,edx
  3260.  
  3261. IFDEF    __16__
  3262.     xor    ebx,ebx
  3263. ENDIF
  3264.     mov    _bx,[updRate]
  3265.     idiv    ebx                ; eax = bytes to play until next update
  3266.     push    eax
  3267.  
  3268.     regsel    84h                ; Sample end position high
  3269.     inc    _dx
  3270.     in    ax,dx
  3271. IFDEF    __16__
  3272.     xor    ebx,ebx
  3273. ENDIF
  3274.     mov    _bx,_ax
  3275.     and    _bx,01fffh
  3276.     shl    ebx,7
  3277.  
  3278.     regsel    85h                ; Sample end position low
  3279.     inc    _dx
  3280.     in    ax,dx
  3281.     shr    ax,9
  3282.     or    _bx,_ax
  3283.  
  3284.     regsel    8ah                ; Current position high
  3285.     inc    _dx
  3286.     in    ax,dx
  3287. IFDEF    __16__
  3288.     xor    ecx,ecx
  3289. ENDIF
  3290.     mov    _cx,_ax
  3291.     and    _cx,01fffh
  3292.     shl    ecx,7
  3293.  
  3294.     regsel    8bh                ; Current position low
  3295.     inc    _dx
  3296.     in    ax,dx
  3297.     shr    ax,9
  3298.     or    _cx,_ax
  3299.  
  3300.     sub    ebx,ecx             ; Bytes to sample / loop end
  3301.     pop    eax
  3302.  
  3303.     cmp    ebx,eax
  3304.     jg    @@retrigged            ; Some sample still to go
  3305.  
  3306.     test    [_si+channels.loopMode],sdLoopAmigaNone ; Looped?
  3307.     je    @@stopsound
  3308.  
  3309.     mov    _ax,[_si+channels.inst]
  3310.     mov    [_si+channels.curinst],_ax
  3311.  
  3312.     cmp    ebx,0
  3313.     jg    @@norm
  3314.  
  3315.     mov    ebx,[_si+channels.sstart]
  3316.     jmp    @@startfromloop
  3317.  
  3318. @@norm: mov    ecx,[_si+channels.send]
  3319.     sub    ecx,ebx
  3320.     mov    ebx,ecx
  3321.  
  3322. @@startfromloop:
  3323. ; EBX = Starting position
  3324.  
  3325.     mov    ecx,[_si+channels.send]        ; Set sample end
  3326.  
  3327.     regsel    4                ; End position high
  3328.     inc    _dx
  3329.     mov    eax,ecx
  3330.     shr    eax,7
  3331.     out    dx,ax
  3332.     regsel    5                ; End position low
  3333.     inc    _dx
  3334.     mov    eax,ecx
  3335.     shl    _ax,9
  3336.     out    dx,ax
  3337.  
  3338.     mov    ecx,[_si+channels.sstart]      ; Set loop start
  3339.  
  3340.     regsel    2                ; Start position high
  3341.     inc    _dx
  3342.     mov    eax,ecx
  3343.     shr    eax,7
  3344.     out    dx,ax
  3345.     regsel    3                ; Start position low
  3346.     inc    _dx
  3347.     mov    eax,ecx
  3348.     shl    _ax,9
  3349.     out    dx,ax
  3350.  
  3351.     regsel    0                ; Voice control
  3352.     mov    al,8                ; Enable voice and loop
  3353.     add    _dx,2
  3354.     out    dx,al
  3355.  
  3356.     regsel    10                ; Current position high
  3357.     inc    _dx
  3358.     mov    eax,ebx
  3359.     shr    eax,7
  3360.     out    dx,ax
  3361.     regsel    11                ; Current position low
  3362.     inc    _dx
  3363.     mov    eax,ebx
  3364.     shl    _ax,9
  3365.     out    dx,ax
  3366.  
  3367.     call    gusdelay            ; Delay
  3368.  
  3369.     out    dx,ax
  3370.  
  3371.     regsel    10                ; Current position high
  3372.     inc    _dx
  3373.     mov    eax,ebx
  3374.     shr    eax,7
  3375.     out    dx,ax
  3376.  
  3377.     regsel    0                ; Voice control
  3378.     add    _dx,2
  3379.     mov    al,8                ; Enable voice and loop
  3380.     out    dx,al
  3381.     jmp    @@retrigged
  3382.  
  3383. @@stopsound:
  3384.     regsel    0                ; Voice control
  3385.     add    _dx,2
  3386.     mov    al,3                ; Stop voice
  3387.     out    dx,al
  3388.  
  3389.     regsel    9                ; Current volume
  3390.     inc    _dx
  3391.     mov    _ax,1500h            ; To zero
  3392.     out    dx,ax
  3393.  
  3394.     regsel    0dh                ; Ramp control
  3395.     add    _dx,2
  3396.     mov    al,3                ; Stop
  3397.     out    dx,al
  3398.  
  3399.     call    gusdelay
  3400.  
  3401.     out    dx,al
  3402.  
  3403.     regsel    0                ; Voice control
  3404.     add    _dx,2
  3405.     mov    al,3                ; Stop voice
  3406.     out    dx,al
  3407.  
  3408.     regsel    9                ; Current volume
  3409.     inc    _dx
  3410.     mov    ax,1500h            ; To zero
  3411.     out    dx,ax
  3412.  
  3413. @@noALE:
  3414. @@retrigged:
  3415.     add    _si,size gusChannel        ; Do all channels in order
  3416.     inc    [chanc]
  3417.     mov    _ax,[chancount]
  3418.  
  3419. IFNDEF NOSTEREO
  3420.     cmp    [mEnableSurround],0
  3421.     je    @@ij
  3422.     add    _ax,_ax             ; Plus Surround channels
  3423. @@ij:
  3424. ENDIF
  3425.     cmp    [chanc],_ax
  3426.     jb    @@loop
  3427.  
  3428. @@waitloop:
  3429.     mov    [chanc],0            ; Start from channel 0
  3430.     xor    _si,_si             ; Channel data
  3431.     mov    [retrigfl],0
  3432. @@loop2:
  3433.     cmp    [_si+channels.onoff],0
  3434.     je    @@skip
  3435.  
  3436.     test    [_si+channels.status],gsRetrig    ; Retrig?
  3437.     jz    @@skip
  3438.  
  3439.     mov    _dx,[voicesel]            ; Select voice
  3440.     mov    _ax,[chanc]
  3441.     out    dx,al
  3442.  
  3443. IFE FASTGUS
  3444.     regsel    8dh                ; Ramp finished?
  3445.     add    _dx,2
  3446.     in    al,dx
  3447.     test    al,1
  3448.     jnz    @@retrig
  3449.  
  3450.     mov    [retrigfl],1            ; Still voice(s) to wait...
  3451.     jmp    @@skip
  3452. ENDIF
  3453. @@retrig:
  3454.     test    [_si+channels.status],gsSample
  3455.     jz    @@not                ; No sample changed
  3456.  
  3457.     mov    ecx,[_si+channels.send]     ; Set sample end
  3458.     cmp    [_si+channels.sampleType],smp16bit
  3459.     jne    @@spl
  3460. ; translate 16 bit sample address...
  3461.     mov    edx,ecx
  3462.     shr    ecx,1
  3463.     and    ecx,01ffffh
  3464.     and    edx,0c0000h
  3465.     xor    ecx,edx
  3466. @@spl:
  3467.     regsel    4                ; End position high
  3468.     inc    _dx
  3469.     mov    eax,ecx
  3470.     shr    eax,7
  3471.     out    dx,ax
  3472.     regsel    5                ; End position low
  3473.     inc    _dx
  3474.     mov    eax,ecx
  3475.     shl    _ax,9
  3476.     out    dx,ax
  3477.  
  3478.     mov    ecx,[_si+channels.sstart]    ; Set loop start
  3479.     cmp    [_si+channels.sampleType],smp16bit
  3480.     jne    @@spl2
  3481. ; translate 16 bit sample address...
  3482.     mov    edx,ecx
  3483.     shr    ecx,1
  3484.     and    ecx,01ffffh
  3485.     and    edx,0c0000h
  3486.     xor    ecx,edx
  3487. @@spl2:
  3488.     regsel    2                ; Start position high
  3489.     inc    _dx
  3490.     mov    eax,ecx
  3491.     shr    eax,7
  3492.     out    dx,ax
  3493.     regsel    3                ; Start position low
  3494.     inc    _dx
  3495.     mov    eax,ecx
  3496.     shl    _ax,9
  3497.     out    dx,ax
  3498.  
  3499.     and    [_si+channels.status],NOT gsSample
  3500.  
  3501. @@not:    regsel    0                ; Voice control
  3502.     add    _dx,2
  3503.     mov    al,3                ; Stop voice
  3504.     out    dx,al
  3505.  
  3506.     mov    ecx,[_si+channels.scurrent]    ; Set starting address
  3507.     cmp    [_si+channels.sampleType],smp16bit
  3508.     jne    @@spl3
  3509. ; translate 16 bit sample address...
  3510.     mov    edx,ecx
  3511.     shr    ecx,1
  3512.     and    ecx,01ffffh
  3513.     and    edx,0c0000h
  3514.     xor    ecx,edx
  3515. @@spl3:
  3516.     regsel    10                ; Current position high
  3517.     inc    _dx
  3518.     mov    eax,ecx
  3519.     shr    eax,7
  3520.     out    dx,ax
  3521.     regsel    11                ; Current position low
  3522.     inc    _dx
  3523.     mov    eax,ecx
  3524.     shl    _ax,9
  3525.     out    dx,ax
  3526.  
  3527.     call    gusdelay
  3528.  
  3529.     out    dx,ax
  3530.  
  3531.     regsel    10                ; Current position high
  3532.     inc    _dx
  3533.     mov    eax,ecx
  3534.     shr    eax,7
  3535.     out    dx,ax
  3536.  
  3537.     regsel    0                ; Voice control
  3538.     add    _dx,2
  3539.     mov    al,3                ; Stop voice
  3540.     out    dx,al
  3541.  
  3542.     mov    _ax,[_si+channels.inst]
  3543.     mov    [_si+channels.curinst],_ax
  3544.  
  3545.     regsel    0                ; Voice control
  3546.     add    dx,2
  3547.     mov    _ax,[_si+channels.loop1Type]    ; Enable voice and possible loop
  3548.     cmp    _ax,loopNone
  3549.     je    @@noloop2
  3550.     cmp    _ax,loopUnidir
  3551.     je    @@loopuni
  3552.  
  3553. @@loopbidi:
  3554.     mov    al,24
  3555.     jmp    @@loopok2
  3556. @@loopuni:
  3557.     mov    al,8
  3558.     jmp    @@loopok2
  3559. @@noloop2:
  3560.     xor    al,al
  3561. @@loopok2:
  3562.     mov    _cx,[_si+channels.sampleType]
  3563.     cmp    _cx,smp16bit
  3564.     jne    @@lok
  3565.     or    al,4
  3566. @@lok:    out    dx,al
  3567.  
  3568.     regsel    8                ; Ramp end
  3569.     add    _dx,2
  3570.     mov    _ax,[_si+channels.volume]    ; To set volume
  3571.  
  3572.     test    [_si+channels.status],gsMute
  3573.     jz    @@oek
  3574.     xor    _ax,_ax
  3575. @@oek:    mov    _bx,[mastervol]
  3576.     mul    bl
  3577.     shr    _ax,6
  3578.     mov    _bx,_ax
  3579.     add    _bx,_bx
  3580.     mov    ax,[voltable+_bx]
  3581.     mov    al,ah
  3582.  
  3583.     cmp    [_si+channels.surround],0
  3584.     je    @@hu
  3585.     sub    al,10h                ; Halve the volume
  3586. @@hu:    out    dx,al
  3587.  
  3588.     regsel    0dh
  3589.     add    _dx,2
  3590.     xor    al,al
  3591.     out    dx,al
  3592.  
  3593.     call    gusdelay            ; Delay
  3594.  
  3595.     out    dx,al
  3596.  
  3597.     regsel    0                ; Voice control
  3598.     add    dx,2
  3599.     mov    _ax,[_si+channels.loop1Type]    ; Enable voice and possible loop
  3600.     cmp    _ax,loopNone
  3601.     je    @@noloop3
  3602.     cmp    _ax,loopUnidir
  3603.     je    @@loopuni2
  3604. @@loopbidi2:
  3605.     mov    al,24
  3606.     jmp    @@loopok3
  3607. @@loopuni2:
  3608.     mov    al,8
  3609.     jmp    @@loopok3
  3610. @@noloop3:
  3611.     xor    al,al
  3612. @@loopok3:
  3613.     cmp    _cx,smp16bit
  3614.     jne    @@lok2
  3615.     or    al,4
  3616. @@lok2: out    dx,al
  3617.  
  3618.     and    [_si+channels.status],NOT (gsRetrig OR gsVolume)
  3619.  
  3620. @@skip: add    _si,size gusChannel        ; Do all channels in order
  3621.     inc    [chanc]
  3622.     mov    _ax,[chancount]
  3623. IFNDEF NOSTEREO
  3624.     cmp    [mEnableSurround],0
  3625.     je    @@ij2
  3626.     add    _ax,_ax             ; Plus Surround channels
  3627. @@ij2:
  3628. ENDIF
  3629.     cmp    [chanc],_ax
  3630.     jb    @@loop2
  3631.  
  3632. IFE FASTGUS
  3633.     cmp    [retrigfl],0            ; Still voices to wait?
  3634.     jne    @@waitloop
  3635. ENDIF
  3636.     mov    _ax,[voicesave]
  3637.     mov    _dx,[voicesel]
  3638.     out    dx,al
  3639.  
  3640.     mov    _ax,[selsave]
  3641.     mov    _dx,[selreg]
  3642.     out    dx,al
  3643.  
  3644.     mov    [masterchanged],0
  3645.  
  3646.     LOADPTR es,_bx,[callMP]
  3647.     mov    [_int _esbx],1            ; Call mp.Play!
  3648. @@done: xor    _ax,_ax
  3649.     ret
  3650.  
  3651. @@paused:
  3652.     LOADPTR es,_bx,[callMP]
  3653.     mov    [_int _esbx],0            ; Don't call mp.Play!
  3654.     jmp    @@done
  3655. ENDP
  3656.  
  3657.  
  3658.  
  3659.  
  3660. ;/***************************************************************************\
  3661. ;*
  3662. ;* Function:    int initHeap()
  3663. ;*
  3664. ;* Description: Initializes the GUS heap
  3665. ;*
  3666. ;* Returns:    MIDAS error code.
  3667. ;*
  3668. ;\***************************************************************************/
  3669.  
  3670.  
  3671. PROC    initHeap NEAR
  3672. USES    _di,_bx
  3673.  
  3674.     mov    _ax,MAXSAMPLES * SIZE ghb
  3675.  
  3676. IFNDEF NOSTEREO
  3677.     cmp    [mEnableSurround],0
  3678.     je    @@kool
  3679.  
  3680.     add    _ax,_ax             ; Room for surround
  3681.                         ; blocks, too
  3682. @@kool:
  3683. ENDIF
  3684.     push    _ax
  3685.     call    memAlloc LANG, _ax, ptr_to temp
  3686.                         ; Alloc room for heap blocks
  3687.     pop    _cx                ; Size to _cx
  3688.     test    _ax,_ax
  3689.     jne    @@err
  3690.  
  3691.     mov    ebx,[temp]
  3692.     mov    [gusHeapStart],ebx
  3693.     mov    [gusHeap],ebx
  3694.  
  3695.     LOADPTR es,_di,[temp]
  3696.     xor    al,al
  3697.                         ; Size already in _cx
  3698.     cld
  3699.     rep    stosb                ; Clear instrument datas
  3700.  
  3701.     LOADPTR es,_bx,[temp]
  3702.     mov    eax,[memamount]
  3703.     mov    [_esbx+ghb.next],0        ; first and last block
  3704.     mov    [_esbx+ghb.gusmem],0        ; from the start of mem
  3705.     mov    [_esbx+ghb.length],eax        ; whole memory
  3706.     xor    _ax,_ax
  3707.     ret
  3708.  
  3709. @@err:    ERROR    ID_gusInitHeap
  3710.     ret
  3711. ENDP
  3712.  
  3713.  
  3714. ;/***************************************************************************\
  3715. ;*
  3716. ;* Function:    int freeHeap()
  3717. ;*
  3718. ;* Description: Uninitializes the GUS heap
  3719. ;*
  3720. ;* Returns:    MIDAS error code.
  3721. ;*
  3722. ;\***************************************************************************/
  3723.  
  3724.  
  3725. PROC    freeHeap NEAR
  3726. USES    _bx
  3727.  
  3728.     call    memFree LANG, [gusHeap]
  3729.     test    _ax,_ax
  3730.     jnz    @@err
  3731.     ret
  3732.  
  3733. @@err:    ERROR    ID_gusFreeHeap
  3734.     ret
  3735. ENDP
  3736.  
  3737.  
  3738. ;/***************************************************************************\
  3739. ;*
  3740. ;* Function:    int gusMalloc(ushort length, ulong *mem)
  3741. ;*
  3742. ;* Description: Allocates GUS memory (with best fit alcorithm)
  3743. ;*
  3744. ;* Input:    ushort length        Length of the block to be allocated
  3745. ;*                    (Rounded up to next 64 bytes with
  3746. ;*                    at least 32 bytes for loop copy, etc.)
  3747. ;*
  3748. ;* Returns:    MIDAS error code.
  3749. ;*
  3750. ;\***************************************************************************/
  3751. PROC    gusMalloc _funct   glength : _int, gtype : _int, mem : _ptr
  3752. USES    _si,_di,_bx
  3753. LOCAL    bestfitoff : _int, bestfitseg : _int, leastslack : dword
  3754.  
  3755. @@again:
  3756. IFDEF    __16__
  3757.     xor    eax,eax
  3758. ENDIF
  3759.     mov    _ax,[glength]
  3760.     test    _ax,_ax
  3761.     jz    @@done
  3762.  
  3763.     mov    ebx,eax         ; Round up to next 64 byte border
  3764.     and    ebx,1fh         ; with at least 32 bytes buffer
  3765.     mov    ecx,64
  3766.     sub    ecx,ebx
  3767.     add    eax,ecx
  3768.  
  3769.     cmp    eax,256*1024
  3770.     jb    @@mok
  3771.  
  3772.     cmp    [gtype],smp16bit
  3773.     je    @@notenoughmem            ; can't play over 256kb
  3774.                         ; 16-; bit samples...
  3775. @@mok:    mov    [bestfitseg],0
  3776.     mov    [leastslack],7ffffffh
  3777.  
  3778.     cmp    [memavail],eax            ; Is there that much memory left
  3779.     jl    @@notenoughmem
  3780.  
  3781.     cmp    [largestblock],eax        ; Do we have to defragment?
  3782.     jg    @@noneedtodefragment
  3783.  
  3784.     push    eax
  3785.     call    gusDefragment
  3786.     pop    eax
  3787.  
  3788.     cmp    [largestblock],eax
  3789.     jl    @@notenoughmem
  3790.  
  3791. @@noneedtodefragment:
  3792.     LOADPTR es,_si,[gusHeapStart]
  3793.  
  3794. @@findbest:
  3795.     push    eax
  3796.     call    findFreeBlock
  3797.     pop    eax
  3798.     jc    @@notanymore
  3799.  
  3800.     mov    ebx,[_essi+ghb.length]
  3801.     and    ebx, NOT 1fh            ; And flags off
  3802.     sub    ebx,eax
  3803.     js    @@nxt                ; Too small
  3804.  
  3805.     cmp    [leastslack],ebx
  3806.     jl    @@nxt                ; Not the best
  3807.  
  3808.     mov    [leastslack],ebx        ; Set to be the best
  3809. IFDEF    __16__
  3810.     mov    _bx,es
  3811.     mov    [bestfitseg],_bx
  3812. ENDIF
  3813.     mov    [bestfitoff],_si
  3814.  
  3815. @@nxt:
  3816.     mov    ecx,[_essi+ghb.next]        ; Advance to next block
  3817.     test    ecx,ecx
  3818.     jz    @@notanymore
  3819.     mov    _si,_cx
  3820. IFDEF    __16__
  3821.     shr    ecx,16
  3822.     mov    es,cx
  3823. ENDIF
  3824.     jmp    @@findbest
  3825.  
  3826. @@notanymore:
  3827. IFDEF    __16__
  3828.     cmp    [bestfitseg],0    ; Was there any free blocks large enough?
  3829.     je    @@notenoughmem
  3830. ELSE
  3831.     cmp    [bestfitoff],0    ; Was there any free blocks large enough?
  3832.     je    @@notenoughmem
  3833. ENDIF
  3834.     cmp    [leastslack],0
  3835.     je    @@justalloc
  3836.  
  3837. @@notfit:
  3838.     push    eax
  3839.     call    allocBlock LANG, ptr_to temp ; Allocate new block
  3840.     test    _ax,_ax
  3841.     jnz    @@memerr
  3842.  
  3843.     pop    eax
  3844.     LOADPTR gs,_di,[temp]
  3845.  
  3846.     mov    _si,[bestfitoff]
  3847. IFDEF    __16__
  3848.     mov    bx,[bestfitseg]
  3849.     mov    es,bx
  3850. ENDIF
  3851.     mov    ebx,[_essi+ghb.gusmem]        ; Copy pointer
  3852.  
  3853.     cmp    [gtype],smp16bit
  3854.     jne    @@kool
  3855.  
  3856.     mov    ecx,ebx
  3857.     mov    edx,ecx
  3858.     add    ecx,eax
  3859.     and    ecx,NOT(256*1024-1)
  3860.     and    edx,NOT(256*1024-1)
  3861.     cmp    ecx,edx
  3862.     je    @@kool                ; Wholly inside one
  3863.                         ; 256k bank
  3864.  
  3865. ; We'll have to split this block to two, one for each bank.
  3866. @@split:
  3867.     mov    ecx,ebx
  3868.     add    ecx,256*1024-1
  3869.     and    ecx,NOT (256*1024-1)
  3870.     mov    [_gsdi+ghb.gusmem],ecx
  3871.     sub    ecx,ebx
  3872.     mov    ebx,[_essi+ghb.length]
  3873.     sub    ebx,ecx
  3874.     mov    [_gsdi+ghb.length],ebx        ; second block length
  3875.     mov    [_essi+ghb.length],ecx        ; first block length
  3876.     mov    ecx,[_essi+ghb.next]
  3877.     mov    ebx,[temp]
  3878.     mov    [_gsdi+ghb.next],ecx
  3879.     mov    [_essi+ghb.next],ebx
  3880.  
  3881.     PUSHSEGREG gs
  3882.     call    checkCoreFree            ; Update biggest block
  3883.     POPSEGREG gs
  3884.     test    _ax,_ax
  3885.     jnz    @@err
  3886.     jmp    @@again
  3887.  
  3888. @@kool:
  3889.     mov    [_gsdi+ghb.gusmem],ebx
  3890.     mov    [_gsdi+ghb.length],eax        ; Set block length
  3891.     or    [_gsdi+ghb.length],1        ; Mark as allocated
  3892.  
  3893.     add    [_essi+ghb.gusmem],eax        ; Move free block "upwards"
  3894.     sub    [_essi+ghb.length],eax        ; Sub free block length
  3895.  
  3896. IFDEF    __16__
  3897.     mov    bx,es
  3898.     shl    ebx,16
  3899. ENDIF
  3900.     mov    _bx,_si
  3901.  
  3902.     mov    [_gsdi+ghb.next],ebx        ; Link blocks
  3903.     cmp    [gusHeapStart],ebx
  3904.     jne    @@notfirst            ; The first block?
  3905.  
  3906. IFDEF    __16__
  3907.     mov    bx,gs                ; Set this block to HeapStart
  3908.     shl    ebx,16
  3909. ENDIF
  3910.     mov    _bx,_di
  3911.     mov    [gusHeapStart],ebx
  3912.     jmp    @@donee
  3913.  
  3914. @@notfirst:
  3915.     push    eax
  3916.     mov    eax,ebx
  3917.     call    findPrevBlock            ; Find block linked to the free block
  3918.     pop    eax
  3919.     jc    @@heapcorr            ; No such block!
  3920.  
  3921. IFDEF    __16__
  3922.     mov    bx,gs
  3923.     shl    ebx,16
  3924. ENDIF
  3925.     mov    _bx,_di
  3926.     mov    [_essi+ghb.next],ebx        ; Link to previous block
  3927.  
  3928.  
  3929. @@donee:
  3930.     sub    [memavail],eax
  3931.     PUSHSEGREG gs
  3932.     call    checkCoreFree            ; Update biggest block
  3933.     POPSEGREG gs
  3934.     test    _ax,_ax
  3935.     jnz    @@err
  3936.     mov    eax,[_gsdi+ghb.gusmem]        ; Return pointer
  3937.     LOADPTR es,_bx,[mem]
  3938.     mov    [_esbx],eax
  3939.     xor    _ax,_ax
  3940.     ret
  3941.  
  3942. @@justalloc:                    ; Realloc?
  3943.     mov    ebx,[_essi+ghb.gusmem]        ; Copy pointer
  3944.  
  3945.     cmp    [gtype],smp16bit
  3946.     jne    @@kool2
  3947.  
  3948.     mov    ecx,ebx
  3949.     mov    edx,ecx
  3950.     add    ecx,eax
  3951.     and    ecx,NOT(256*1024-1)
  3952.     and    edx,NOT(256*1024-1)
  3953.     cmp    ecx,edx
  3954.     jne    @@notfit            ; we'll have to split...
  3955. @@kool2:
  3956.     or    [_essi+ghb.length],1
  3957.     sub    [memavail],eax
  3958.     PUSHSEGREG es
  3959.     call    checkCoreFree
  3960.     POPSEGREG es
  3961.     test    _ax,_ax
  3962.     jnz    @@err
  3963.     mov    eax,[_essi+ghb.gusmem]
  3964. @@done: LOADPTR es,_bx,[mem]
  3965.     mov    [_esbx],eax
  3966.     xor    _ax,_ax
  3967.     ret
  3968.  
  3969. @@memerr:
  3970.     pop    ebx                ; pop saved pointer
  3971.     jmp    @@err
  3972.  
  3973. @@heapcorr:
  3974.     mov    _ax,errCardHeapCorrupted
  3975.     jmp    @@err
  3976.  
  3977. @@notenoughmem:
  3978.     mov    _ax,errOutOfCardMemory
  3979. @@err:    ERROR    ID_gusMalloc
  3980.     ret
  3981. ENDP
  3982.  
  3983.  
  3984.  
  3985. ;/***************************************************************************\
  3986. ;*
  3987. ;* Function:    int gusFree(ulong mem)
  3988. ;*
  3989. ;* Description: Deallocates GUS memory
  3990. ;*
  3991. ;* Input:    ulong block        Pointer to allocated GUS mem
  3992. ;*
  3993. ;* Returns:    1 if success, 0 if not
  3994. ;*
  3995. ;* Destroys:    ax, bx, cx, dx
  3996. ;*
  3997. ;\***************************************************************************/
  3998. PROC    gusFree _funct     block : dword
  3999. USES    _si,_di,_bx
  4000. LOCAL    freed : dword
  4001.  
  4002.     mov    eax,[block]
  4003.  
  4004.     LOADPTR gs,_di,[gusHeapStart]
  4005. @@sloop:
  4006.     cmp    [_gsdi+ghb.gusmem],eax
  4007.     je    @@found
  4008.  
  4009.     mov    ebx,[_gsdi+ghb.next]
  4010.     test    ebx,ebx
  4011.     jz    @@invalid
  4012.     mov    _di,_bx
  4013. IFDEF    __16__
  4014.     shr    ebx,16
  4015.     mov    gs,bx
  4016. ENDIF
  4017.     jmp    @@sloop
  4018.  
  4019. @@found:
  4020.     test    [_gsdi+ghb.length],1
  4021.     jz    @@heapcorr            ; Not even allocated
  4022.  
  4023.     and    [_gsdi+ghb.length],NOT 1    ; Free this block
  4024.  
  4025.     mov    ebx,[_gsdi+ghb.length]
  4026.     mov    [freed],ebx
  4027.  
  4028.     mov    ebx,[_gsdi+ghb.next]
  4029.     test    ebx,ebx
  4030.     jz    @@nonextblock            ; Last block
  4031.  
  4032.     mov    _si,_bx
  4033. IFDEF    __16__
  4034.     shr    ebx,16
  4035.     mov    es,bx
  4036. ENDIF
  4037.     test    [_essi+ghb.length],1
  4038.     jnz    @@nonextblock            ; Next allocated -> Can't merge blocks
  4039.  
  4040.     mov    edx,[_essi+ghb.next]
  4041.     mov    [_gsdi+ghb.next],edx
  4042.     mov    edx,[_essi+ghb.length]        ; Merge blocks
  4043.     add    [_gsdi+ghb.length],edx
  4044.  
  4045.     PUSHSEGREG gs
  4046. IFDEF    __16__
  4047.     call    freeBlock LANG, es si        ; Free block
  4048. ELSE
  4049.     call    freeBlock LANG, esi        ; Free block
  4050. ENDIF
  4051.     POPSEGREG gs
  4052.     test    _ax,_ax
  4053.     jnz    @@err
  4054.  
  4055. @@nonextblock:
  4056. IFDEF    __16__
  4057.     mov    bx,gs
  4058.     shl    ebx,16
  4059. ENDIF
  4060.     mov    _bx,_di
  4061.     cmp    [gusHeapStart],ebx
  4062.     je    @@firstblock            ; First block
  4063.  
  4064.     mov    eax,ebx
  4065.     call    findPrevBlock
  4066.     jc    @@heapcorr            ; No such block! (Heap corrupt?)
  4067.  
  4068.     test    [_essi+ghb.length],1
  4069.     jnz    @@firstblock            ; previous allocated -> can't merge blocks
  4070.  
  4071.     mov    edx,[_gsdi+ghb.next]
  4072.     mov    [_essi+ghb.next],edx
  4073.     mov    edx,[_gsdi+ghb.length]        ; Merge blocks
  4074.     add    [_essi+ghb.length],edx
  4075.  
  4076. IFDEF    __16__
  4077.     call    freeBlock LANG, gs di        ; Free block
  4078. ELSE
  4079.     call    freeBlock LANG, edi        ; Free block
  4080. ENDIF
  4081.     test    _ax,_ax
  4082.     jnz    @@err
  4083.  
  4084. @@firstblock:
  4085.     mov    eax,[freed]
  4086.     add    [memavail],eax
  4087.     call    checkCoreFree
  4088.     test    _ax,_ax
  4089.     jnz    @@err
  4090.     xor    _ax,_ax
  4091.     ret
  4092.  
  4093. @@heapcorr:
  4094.     mov    _ax,errCardHeapCorrupted
  4095.     jmp    @@err
  4096.  
  4097. @@invalid:
  4098.     mov    _ax,errInvalidBlock
  4099. @@err:    ERROR    ID_gusFree
  4100.     ret
  4101. ENDP
  4102.  
  4103.  
  4104. PROC    allocBlock NEAR block : _ptr
  4105. uses    _bx
  4106.  
  4107.     LOADPTR es,_bx,[gusHeapStart]
  4108.     mov    _cx,MAXSAMPLES
  4109.     cmp    [mEnableSurround],0
  4110.     je    @@findloop
  4111.     add    _cx,_cx             ; Include surround blocks
  4112. @@findloop:
  4113.     cmp    [_esbx+ghb.length],0
  4114.     je    @@found
  4115.     add    _bx,size ghb
  4116.     dec    _cx
  4117.     jnz    @@findloop
  4118.     jmp    @@err
  4119. @@found:
  4120. IFDEF    __16__
  4121.     mov    ax,es
  4122.     shl    eax,16
  4123. ENDIF
  4124.     mov    _ax,_bx
  4125.     LOADPTR es,_bx,[block]
  4126.     mov    [_esbx],eax
  4127.     xor    _ax,_ax
  4128.     ret
  4129.  
  4130. @@err:    mov    _ax,errInvalidBlock
  4131.     ERROR    ID_gusAllocBlock
  4132.     ret
  4133. ENDP
  4134.  
  4135. PROC    freeBlock NEAR block : _ptr
  4136. USES    _bx
  4137.  
  4138.     LOADPTR es,_bx,[block]
  4139.     mov    [_esbx+ghb.next],0
  4140.     mov    [_esbx+ghb.gusmem],0
  4141.     mov    [_esbx+ghb.length],0
  4142.     xor    _ax,_ax
  4143.     ret
  4144. ENDP
  4145.  
  4146. ; _essi = pointer to current block
  4147. ; Returns: _essi = next free block
  4148. ; Carry set if not found
  4149.  
  4150. PROC    findFreeBlock NEAR
  4151.  
  4152. @@sloop:
  4153.     test    [_essi+ghb.length],1
  4154.     jz    @@found
  4155.  
  4156.     mov    eax,[_essi+ghb.next]   ; Advance to next block
  4157.     test    eax,eax
  4158.     jz    @@nofree
  4159.     mov    _si,_ax
  4160. IFDEF    __16__
  4161.     shr    eax,16
  4162.     mov    es,ax
  4163. ENDIF
  4164.     jmp    @@sloop
  4165.  
  4166. @@found:
  4167.     clc
  4168.     ret
  4169. @@nofree:
  4170.     stc
  4171.     ret
  4172. ENDP
  4173.  
  4174.  
  4175. ; eax = pointer to current block
  4176. ; Returns: _essi = prev block
  4177. ; Carry set if not found
  4178.  
  4179. PROC    findPrevBlock NEAR
  4180.  
  4181.     LOADPTR es,_si,[gusHeapStart]
  4182. @@sloop:
  4183.     cmp    [_essi+ghb.next],eax
  4184.     je    @@found
  4185.  
  4186.     mov    ebx,[_essi+ghb.next]
  4187.     test    ebx,ebx
  4188.     jz    @@done
  4189.     mov    _si,_bx
  4190. IFDEF    __16__
  4191.     shr    ebx,16
  4192.     mov    es,bx
  4193. ENDIF
  4194.     jmp    @@sloop
  4195.  
  4196. @@found:
  4197.     clc
  4198.     ret
  4199. @@done:
  4200.     stc
  4201.     ret
  4202. ENDP
  4203.  
  4204.  
  4205.  
  4206. ; No parameters, also checks heap integrity
  4207. ; Returns MIDAS error code
  4208.  
  4209. PROC    checkCoreFree    NEAR
  4210. USES    _si,_bx
  4211.  
  4212.     LOADPTR es,_si,[gusHeapStart]
  4213.     xor    edx,edx             ; Start from size 0
  4214.     xor    ecx,ecx             ; Total mem size
  4215. @@findloop:
  4216.     mov    eax,[_essi+ghb.length]
  4217.     mov    ebx,eax
  4218.     and    ebx,NOT 31            ; ebx = size
  4219.     add    ecx,ebx             ; Add to total
  4220.     test    eax,1                ; Allocated flag
  4221.     jnz    @@findnext            ; Allocated
  4222.     cmp    ebx,edx             ; Largest?
  4223.     jle    @@findnext
  4224.     mov    edx,ebx
  4225. @@findnext:
  4226.     mov    eax,[_essi+ghb.next]   ; Advance to next block
  4227.     test    eax,eax
  4228.     jz    @@done
  4229.     mov    _si,_ax
  4230. IFDEF    __16__
  4231.     shr    eax,16
  4232.     mov    es,ax
  4233. ENDIF
  4234.     jmp    @@findloop
  4235.  
  4236. @@done: mov    [largestblock],edx
  4237.     cmp    [memamount],ecx         ; All memory in heap?
  4238.     jne    @@heapcorr            ; heap corrupt!
  4239.     xor    _ax,_ax
  4240.     ret
  4241.  
  4242. @@heapcorr:
  4243.     mov    _ax,errCardHeapCorrupted
  4244.     ERROR    ID_gusCoreFree
  4245.     ret
  4246. ENDP
  4247.  
  4248. ;/***************************************************************************\
  4249. ;*
  4250. ;* Function:    gusDefragment
  4251. ;*
  4252. ;* Description: Defragments the GUS memory
  4253. ;*
  4254. ;\***************************************************************************/
  4255. PROC    gusDefragment _funct
  4256.     ret
  4257. ENDP
  4258.  
  4259.  
  4260. ;* $Log: gus.asm,v $
  4261. ;* Revision 1.3  1997/01/16 18:41:59  pekangas
  4262. ;* Changed copyright messages to Housemarque
  4263. ;*
  4264. ;* Revision 1.2  1996/08/04 11:27:42  pekangas
  4265. ;* All functions now preserve _bx
  4266. ;*
  4267. ;* Revision 1.1  1996/05/22 20:49:33  pekangas
  4268. ;* Initial revision
  4269. ;*
  4270.  
  4271.  
  4272. END